Beispiel #1
0
    def _solve(self, node, depends):
        ""
        for otherpluginid in depends:
            # check if required plugin is present
            if otherpluginid not in self._nodes:
                if self._nodes[otherpluginid].state == PluginState.Unloaded:
                    return exceptions.PluginError(
                        node, "A required plugin failed to load: {}".format(otherpluginid))
                elif self._nodes[otherpluginid].state == PluginState.Disabled:
                    return exceptions.PluginError(
                        node,
                        "A required plugin has been disabled: {}".format(otherpluginid))
                else:
                    return exceptions.PluginError(
                        node, "A required plugin is not present: {}".format(otherpluginid))

            vers = depends[otherpluginid]
            other_node = self._nodes[otherpluginid]
            # compare versions
            other_version = other_node.plugin.VERSION
            if not vers[0] <= other_version:
                return exceptions.PluginError(
                    node,
                    "A required plugin does not meet version requirement {} <= {}: {}".format(
                        vers[0],
                        other_version,
                        otherpluginid))
            if not vers[1] == (0, 0, 0) and not vers[1] > other_version:
                return exceptions.PluginError(
                    node,
                    "A required plugin does not meet version requirement {} > {}: {}".format(
                        vers[1],
                        other_version,
                        otherpluginid))
        return True
Beispiel #2
0
def _plugin_load(module_name_or_class, path, *args, _logger=None, **kwargs):
    """
    Imports plugin module and registers its main class

    Returns:
        PluginNode
    """
    plugclass = None
    if isinstance(module_name_or_class, str):
        mod = importlib.import_module(module_name_or_class)
        mod = importlib.reload(mod)
        plugmembers = inspect.getmembers(mod)
        for name, m_object in plugmembers:
            if name == "HPlugin":
                plugclass = m_object
                break
    elif inspect.isclass(module_name_or_class):
        plugclass = module_name_or_class
    if plugclass is None:
        raise exceptions.PluginError(
            "Plugin loader",
            "No main entry class named 'HPlugin' found in '{}'".format(path))
    log.i("Loading", plugclass.__name__)
    cls = HPluginMeta(
        plugclass.__name__,
        plugclass.__bases__,
        dict(
            plugclass.__dict__))
    if not _logger:
        _logger = get_plugin_logger(cls.NAME, path)
    return registered.register(cls, _logger, *args, **kwargs)
Beispiel #3
0
 def _init_plugin(self, pluginid):
     ""
     if pluginid in self._nodes:
         node = self._nodes[pluginid]
         try:
             self._ensure_valid_signature(node)
             node.instanced = node.plugin(*node.args, **node.kwargs)
         except Exception as e:
             self.disable_plugin(pluginid)
             if not isinstance(e, exceptions.PluginError):
                 raise exceptions.PluginError(node, "{}".format(e))
             raise
         node.state = PluginState.Enabled
     else:
         raise exceptions.CoreError(
             utils.this_function(),
             "Plugin node has not been registered with this manager")
Beispiel #4
0
    def register(self, plugin, logger, *args, **kwargs):
        """
        Registers a plugin

        Params:
            - plugin -- main plugin class
            - logger -- plugin logger
            - *args -- additional arguments for plugin
            - **kwargs -- additional keyword arguments for plugin

        Returns:
            PluginNode
        """
        assert isinstance(plugin, HPluginMeta)
        if plugin.ID in self._nodes:
            raise exceptions.PluginError(
                plugin.NAME, "Plugin ID already exists")
        node = PluginNode(plugin, logger, *args, **kwargs)
        self._nodes[plugin.ID] = node
        return node
Beispiel #5
0
 def _ensure_before_init(self, node):
     ""
     assert isinstance(node, PluginNode)
     if not node.state == PluginState.Init:
         raise exceptions.PluginError(
             node, "This method should be called in __init__")
Beispiel #6
0
 def _ensure_ready(self, node):
     ""
     assert isinstance(node, PluginNode)
     if not node.state == PluginState.Enabled:
         raise exceptions.PluginError(node, "This plugin is not ready")
Beispiel #7
0
    def _solve(self, nodes):
        """
        Returns a tuple of:
            - An ordered list of node, in the order they should be initiated in
            - Nodes that failed the dependency resolving {node:exception}
        """
        failed = {}

        universal = []
        inverse = []
        provides = {}

        # solve hard requirements
        for node in nodes:
            for otherpluginid in node.depends:
                formatted = format_plugin(otherpluginid)
                # check if required plugin is present
                e = None
                if otherpluginid in self._nodes:
                    if self._nodes[
                            otherpluginid].state == PluginState.Unloaded:
                        e = exceptions.PluginError(
                            node,
                            "A required plugin failed to load: {}".format(
                                formatted))
                    elif self._nodes[
                            otherpluginid].state == PluginState.Disabled:
                        e = exceptions.PluginError(
                            node,
                            "A required plugin has been disabled: {}".format(
                                formatted))
                else:
                    e = exceptions.PluginError(
                        node, "A required plugin is not present: {}".format(
                            formatted))

                if not e:
                    vers = node.depends[otherpluginid]
                    other_node = self._nodes[otherpluginid]
                    # compare versions
                    other_version = other_node.plugin.VERSION
                    if not vers[0] <= other_version:
                        e = exceptions.PluginError(
                            node,
                            "A required plugin does not meet version requirement {} <= {}: {}"
                            .format(vers[0], other_version, formatted))
                    if not vers[1] == (0, 0,
                                       0) and not vers[1] > other_version:
                        e = exceptions.PluginError(
                            node,
                            "A required plugin does not meet version requirement {} > {}: {}"
                            .format(vers[1], other_version, formatted))
                if e:
                    failed[node] = e
                    break
            else:
                provides[node.plugin.ID] = node
                provides[node.plugin.SHORTNAME] = node

                if node.load_order == "first":
                    universal.append(node)
                elif node.load_order == "last":
                    inverse.append(node)

        # build initial graph

        dependencies = {}

        for node in nodes:

            reqs = set(node.depends.keys())
            dependencies[node] = set(provides[x] for x in reqs)

            if universal and node not in universal:
                dependencies[node].update(universal)

            if inverse and node in inverse:
                dependencies[node].update(set(nodes).difference(inverse))

        # solver
        dependencies = robust_topological_sort(dependencies)

        node_order = []
        for node in dependencies:
            # circular reference
            if len(node) > 1:
                for n in node:
                    failed[n] = exceptions.PluginError(
                        "Circular dependency found: {}".format(node))
                continue

            node_order.append(node[0])

        node_order.reverse()

        return node_order, failed