def check_conflicts(self, pkg): """ Check the conflicts between pkg and global list of provides or loaded plugins. The return list contains entry like: (phase-number:int, (p_name:str, p_op:Operator, p_ver:Version) -> Provider (c_name:str, c_op:Operator, c_ver:Version) -> Conflicter ) @param pkg the plugin to check @return [] if everything is OK or a list of plugins conflicting with pkg """ lst = [] # # 1) We should check the cache conflicts agains pkg for provide in pkg.provides: try: name, op, ver = Version.extract_version(provide) if not name in self.who_conflicts: continue for c_op, c_ver, c_pkg in self.who_conflicts[name]: # We could have # c_op, c_ver >=, 2.0.0 # ver = 3.0.0 # We could have a None if a conflict entry didn't provide # any version or operator if c_op.op_str == '.' or c_op(ver, c_ver) is True: lst.append( (1, (name, op, ver), # Provider (c_pkg, c_op, c_ver) # Conflicter ) ) except Exception, err: log.error(err) log.error("1) Ignoring conflict entry ...") continue
def check_needs(self, pkg): """ Check the needs between pkg and global list of provides. The return list contains entry like: (name:str, op:Operator, ver:Version) -> need not found @param pkg the plugin to check @return [] if everything is OK or a list of not resolved needs """ # We have passed the conflict stage # so check for needs lst = [] for need in pkg.needs: try: found = False name, op, ver = Version.extract_version(need) if not name in self.who_provides: lst.append((name, op, ver)) continue for n_op, n_ver, n_pkg in self.who_provides[name]: # for example we could have # name, op, ver = dummy, >=, 2.0.0 # n_ver = 2.0.3 # TODO: check me if op(n_ver, ver) is True or op(n_ver, ver) is None: found = True break # If we are here not applicable deps were found so add if not found: lst.append((name, op, ver)) except Exception, err: log.error(err) log.error("Ignoring need entry ...") continue
def load_directory(self, modpath): if not os.environ.get('UMIT_DEVELOPMENT', False): log.error("This method should not be called in release.") return start_file = 'main' log.warning("You are loading a plugin without checking for needs,provides,conflitcts") log.warning("* You have been warned! *") log.warning("Assuming `%s' as start file!" % start_file) # Load the plugin sys.path.insert(0, os.path.abspath(modpath)) if start_file in sys.modules: sys.modules.pop(start_file) try: __builtin__.__import__ = hook_import module = hook_import(start_file, level=0) if hasattr(module, "__plugins__") and \ isinstance(module.__plugins__, list): lst = module.__plugins__ ret = [] for plug in lst: try: inst = plug() inst.start(None) ret.append(inst) except Exception, err: log.critical("Error while starting %s:" % (plug)) log.critical(generate_traceback()) log.critical("Ignoring instance.") if not ret: log.error("Not startable plugin defined in main file") else:
def __remove_file(self, obj): try: obj.fd.close() os.remove(obj.fd.name) except: log.error('Error while removing temp %s file' % obj.fd.name)
def proxy(*args, **kwargs): try: func(*args, **kwargs) except Exception, err: log.error(_('>>> safecall(): Ignoring exception %s -> %s (%s, %s)')\ % (err, func, args, kwargs))
class PluginsTree(object): """ Manages and tracks the loads/unloads of plugins objects """ def __init__(self): """ Create a new PluginsTree @param parent a PluginEngine instance """ # A dict to trace plugin instances self.instances = {} self.modules = {} self.who_conflicts, \ self.who_provides, \ self.who_needs = DepDict(), DepDict(), DepDict() self.pkg_lst = list() def dump(self): log.info(">>> dump(): conflicts/provides/needs: %d / %d / %d" % \ ( len(self.who_conflicts), len(self.who_provides), len(self.who_needs) ) ) def check_conflicts(self, pkg): """ Check the conflicts between pkg and global list of provides or loaded plugins. The return list contains entry like: (phase-number:int, (p_name:str, p_op:Operator, p_ver:Version) -> Provider (c_name:str, c_op:Operator, c_ver:Version) -> Conflicter ) @param pkg the plugin to check @return [] if everything is OK or a list of plugins conflicting with pkg """ lst = [] # # 1) We should check the cache conflicts agains pkg for provide in pkg.provides: try: name, op, ver = Version.extract_version(provide) if not name in self.who_conflicts: continue for c_op, c_ver, c_pkg in self.who_conflicts[name]: # We could have # c_op, c_ver >=, 2.0.0 # ver = 3.0.0 # We could have a None if a conflict entry didn't provide # any version or operator if c_op.op_str == '.' or c_op(ver, c_ver) is True: lst.append( (1, (name, op, ver), # Provider (c_pkg, c_op, c_ver) # Conflicter ) ) except Exception, err: log.error(err) log.error("1) Ignoring conflict entry ...") continue # # 2) We should check the package conflicts against cache provides for conflict in pkg.conflicts: try: name, op, ver = Version.extract_version(conflict) if not name in self.who_provides: continue # Only '=' operator presents: # providers['woot'] = [('=', '2.0', pkg1), ('=', '2.1', pkg2), ..] for p_op, p_ver, p_pkg in self.who_provides[name]: # for example we could have # name, op, ver = dummy, >=, 2.0.0 # p_ver = 2.0.3 # strict checking for avoid false results # if None was returned if op(p_ver, ver) is True: # So we have a conflict. Just add to the list lst.append( (2, (p_pkg, p_op, p_ver), # Provider (name, op, ver) # Conflicter ) ) except Exception, err: log.error(err) log.error("2) Ignoring conflict entry ...") continue
for plug in lst: try: inst = plug() inst.start(None) ret.append(inst) except Exception, err: log.critical("Error while starting %s:" % (plug)) log.critical(generate_traceback()) log.critical("Ignoring instance.") if not ret: log.error("Not startable plugin defined in main file") else: log.error("No Plugin subclass") finally: __builtin__.__import__ = original_import def __load_hook(self, pkg): """ This is the real load procedure of plugin. We'll use zipmodule to import and a global function expose to provide a simple method to access files inside the zip file to plugin. Raise a PluginException on fail @return None or raise a PluginException """