def check_list_needs(self, pkg): """ Check the needs from list against pkg @param pkg the plugin to check @return [] if everything is OK or a list of not used needs (name, op, version) """ # Clone the list and drops out pkg lst = self.pkg_lst[:] lst.remove(pkg) conflicts_lst = [] for provide in pkg.provides: p_name, p_op, p_ver = Version.extract_version(provide) for n_pkg in lst: for need in n_pkg.needs: n_name, n_op, n_ver = Version.extract_version(need) if n_name != p_name: continue # It's our need and we have a dep! :D if n_op(p_ver, n_ver) is True: conflicts_lst.append((n_pkg, n_op, n_ver)) return conflicts_lst
def add_plugin_to_cache(self, pkg): """ Exports the needs/provides/conflicts to the global dicts """ for attr in ('conflicts', 'provides', 'needs'): for dep in getattr(pkg, attr, []): try: name, op, ver = Version.extract_version(dep) d = getattr(self, "who_%s" % attr) d[name] = (op, ver, pkg) except Exception, err: log.warning(err) log.warning("Ignoring %s entry" % dep)
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 get_need(self, reader, needstr, classname=None, need_module=False): """ Usefull function to return an instance of needstr:classname @param reader a PluginReader object or None """ lst = [] if reader: # We create a list of needs for the same package for need in reader.needs: name, op, ver = Version.extract_version(need) if name == needstr: lst.append((op, ver, name)) from umit.pm.gui.plugins.engine import PluginEngine ret = PluginEngine().tree.get_provide(needstr, lst, need_module) log.debug(">>> Core.get_need() -> %s (module: %s)" % (ret, need_module)) if not ret: return None if not need_module: if not classname: log.debug(">>> Core.get_need(): No classname specified. " \ "Returning first instance") return ret[0] for instance in ret: if instance.__class__.__name__ == classname: return instance else: # We need a module if len(ret) > 1: log.debug(">>> Core.get_need(): Returning the first module") return ret[0] return None
def get_need(self, reader, needstr, classname=None, need_module=False): """ Usefull function to return an instance of needstr:classname @param reader a PluginReader object or None """ lst = [] if reader: # We create a list of needs for the same package for need in reader.needs: name, op, ver = Version.extract_version(need) if name == needstr: lst.append((op, ver, name)) from umit.pm.gui.plugins.engine import PluginEngine ret = PluginEngine().tree.get_provide(needstr, lst, need_module) log.debug(">>> Core.get_need() -> %s (module: %s)" % (ret, need_module)) if not ret: return None if not need_module: if not classname: log.debug(">>> Core.get_need(): No classname specified. " \ "Returning first instance") return ret[0] for instance in ret: if instance.__class__.__name__ == classname: return instance else: # We need a module if len(ret) > 1: log.debug(">>> Core.get_need(): Returning the first module") return ret[0] return None
def remove_plugin_from_cache(self, pkg): for attr in ('conflicts', 'provides', 'needs'): for dep in getattr(pkg, attr, []): try: name, op, ver = Version.extract_version(dep) d = getattr(self, "who_%s" % attr) # It's more probably that the entry is in the last for i in xrange(len(d[name]) - 1, -1, -1): _op, _ver, _pkg = d[name][i] if pkg == _pkg and \ ver == _ver and \ op == _op: del d[name][i] # Remove unused keys. if not d[name]: del d[name] except Exception, err: log.warning(err) log.warning("Ignoring %s entry" % dep)
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