From 12918718f9fe702f41e997cdad983613c87ab386 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Sat, 1 May 2010 21:30:15 +0000 Subject: [PATCH] 3879: Allow multiple versions of a plugin svn: r15299 --- src/cli/grampscli.py | 2 +- src/gen/plug/_manager.py | 38 ++++++++++++++++++++++++++++++++------ src/gen/plug/_pluginreg.py | 29 ++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/cli/grampscli.py b/src/cli/grampscli.py index e83b6d970..2138aeb7b 100644 --- a/src/cli/grampscli.py +++ b/src/cli/grampscli.py @@ -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): """ diff --git a/src/gen/plug/_manager.py b/src/gen/plug/_manager.py index bb92aa3b4..9a1187669 100644 --- a/src/gen/plug/_manager.py +++ b/src/gen/plug/_manager.py @@ -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 diff --git a/src/gen/plug/_pluginreg.py b/src/gen/plug/_pluginreg.py index 2be679a12..0c224edf3 100644 --- a/src/gen/plug/_pluginreg.py +++ b/src/gen/plug/_pluginreg.py @@ -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])]