3879: Allow multiple versions of a plugin

svn: r15299
This commit is contained in:
Doug Blank 2010-05-01 21:30:15 +00:00
parent 39f4ac256f
commit 12918718f9
3 changed files with 57 additions and 12 deletions

View File

@ -287,7 +287,7 @@ class CLIManager(object):
Register the plugins at initialization time.
"""
self._pmgr.reg_plugins(const.PLUGINS_DIR)
self._pmgr.reg_plugins(const.USER_PLUGINS)
self._pmgr.reg_plugins(const.USER_PLUGINS, append=False)
def startcli(errors, argparser):
"""

View File

@ -96,7 +96,7 @@ class BasePluginManager(object):
self.__registereddir_set = set()
self.__loaded_plugins = {}
def reg_plugins(self, direct):
def reg_plugins(self, direct, append=True):
"""
Searches the specified directory, and registers python plugin that
are being defined in gpr.py files.
@ -118,7 +118,8 @@ class BasePluginManager(object):
if dirname.startswith(".") or dirname in ["po", "locale"]:
dirnames.remove(dirname)
# add the directory to the python search path
sys.path.append(dirpath)
if append:
sys.path.append(dirpath)
# if the path has not already been loaded, save it in the
# registereddir_list list for use on reloading.
self.__registereddir_set.add(dirpath)
@ -165,14 +166,13 @@ class BasePluginManager(object):
del self.__failmsg_list[index]
else:
self.__attempt_list.append(filename)
plugin = pdata.mod_name
try:
_module = __import__(plugin)
_module = self.import_plugin(pdata)
if need_reload:
# For some strange reason second importing of a failed plugin
# results in success. Then reload reveals the actual error.
# Looks like a bug in Python.
reload(_module)
_module = self.reload(_module, pdata)
self.__success_list.append((filename, _module, pdata))
self.__modules[filename] = _module
self.__loaded_plugins[pdata.id] = _module
@ -183,6 +183,23 @@ class BasePluginManager(object):
return None
def import_plugin(self, pdata):
"""
Rather than just __import__(id), this will add the pdata.fpath
to sys.path first (if needed), import, and then reset path.
"""
if isinstance(pdata, basestring):
pdata = self.get_plugin(pdata)
if not pdata:
return None
if pdata.fpath not in sys.path:
sys.path.insert(0, pdata.fpath)
module = __import__(pdata.mod_name)
sys.path.pop(0)
else:
module = __import__(pdata.mod_name)
return module
def empty_managed_plugins(self):
""" For some plugins, managed Plugin are used. These are only
reobtained from the registry if this method is called
@ -216,7 +233,7 @@ class BasePluginManager(object):
#module already reloaded, a second plugin in same module
continue
try:
reload(plugin[1])
self.reload(plugin[1], pdata)
self.__modules[filename] = plugin[1]
self.__loaded_plugins[pdata.id] = plugin[1]
except:
@ -235,6 +252,15 @@ class BasePluginManager(object):
for (filename, message, pdata) in oldfailmsg:
self.load_plugin(pdata)
def reload(self, module, pdata):
"""
"""
try:
reload(module)
except:
module = self.import_plugin(pdata)
return module
def get_fail_list(self):
""" Return the list of failed plugins. """
return self.__failmsg_list

View File

@ -137,6 +137,22 @@ END = 2
# Functions and classes
#
#-------------------------------------------------------------------------
def myint(s):
"""
Protected version of int()
"""
try:
v = int(s)
except:
v = s
return v
def version(sversion):
"""
Return the tuple version of a string version.
"""
return tuple([myint(x or "0") for x in (sversion + "..").split(".")])
def valid_plugin_version(plugin_version_string):
"""
Checks to see if string is a valid version string for this version
@ -1067,15 +1083,17 @@ class PluginRegister(object):
def get_plugin(self, id):
"""Return the PluginData for the plugin with id"""
for x in self.__plugindata:
if x.id == id:
return x
matches = [x for x in self.__plugindata if x.id == id]
matches.sort(key=lambda x: version(x.version))
if len(matches) > 0:
return matches[-1]
return None
def type_plugins(self, ptype):
"""Return a list of PluginData that are of type ptype
"""
return [x for x in self.__plugindata if x.ptype == ptype]
return [self.get_plugin(id) for id in
set([x.id for x in self.__plugindata if x.ptype == ptype])]
def report_plugins(self, gui=True):
"""Return a list of gui or cli PluginData that are of type REPORT
@ -1158,4 +1176,5 @@ class PluginRegister(object):
def filter_load_on_reg(self):
"""Return a list of PluginData that have load_on_reg == True
"""
return [x for x in self.__plugindata if x.load_on_reg == True]
return [self.get_plugin(id) for id in
set([x.id for x in self.__plugindata if x.load_on_reg == True])]