示例#1
0
def available_importers(pm: PluginManager) -> Set[str]:
    plugins: Dict[str, Any] = dict(pm.list_name_plugin())
    supported_file_types = {
        name[len(IMPORTER_PREFIX) :]
        for name in plugins
        if name.startswith(IMPORTER_PREFIX)
    }
    return supported_file_types
示例#2
0
class SimplePluginManager(object):
    """
    A PluginManager class for simple, non-scanning related plugins.
    """

    def __init__(self, project_name, entrypoint, plugin_base_class):
        """
        Initialize this plugin manager for the fully qualified Python module
        name `module_qname` with plugins loaded from the setuptools `entrypoint`
        that must subclass `plugin_base_class`.
        """
        self.manager = PluggyPluginManager(project_name=project_name)
        self.entrypoint = entrypoint
        self.plugin_base_class = plugin_base_class
        self.manager.add_hookspecs(sys.modules[project_name])

        # set to True once this manager is initialized by running its setup()
        self.initialized = False

        # mapping of {plugin.name: plugin_class} for all the loaded plugins of
        # this manager
        self.plugin_classes = OrderedDict()

    def setup(self):
        """
        Load and validate available plugins for this PluginManager from its
        assigned `entrypoint`. Raise an Exception if a plugin is not valid such
        that when it does not subcclass the manager `plugin_base_class`.
        Must be called once to initialize the plugins if this manager.

        Return a list of all plugin classes for this manager.
        """
        if self.initialized:
            return self.plugin_classes.values()

        entrypoint = self.entrypoint
        self.manager.load_setuptools_entrypoints(entrypoint)

        plugin_classes = []
        for name, plugin_class in self.manager.list_name_plugin():
            if not issubclass(plugin_class, self.plugin_base_class):
                plugin_base_class = self.plugin_base_class
                raise Exception(
                    'Invalid plugin: %(name)r: %(plugin_class)r '
                    'must extend %(plugin_base_class)r.' % locals())

            plugin_class.name = name
            plugin_classes.append(plugin_class)

        self.plugin_classes = OrderedDict([(cls.name, cls) for cls in plugin_classes])
        self.initialized = True
        return self.plugin_classes.values()
示例#3
0
def test_pm(pm: PluginManager) -> None:
    """Basic registration with objects"""
    class A:
        pass

    a1, a2 = A(), A()
    pm.register(a1)
    assert pm.is_registered(a1)
    pm.register(a2, "hello")
    assert pm.is_registered(a2)
    out = pm.get_plugins()
    assert a1 in out
    assert a2 in out
    assert pm.get_plugin("hello") == a2
    assert pm.unregister(a1) == a1
    assert not pm.is_registered(a1)

    out2 = pm.list_name_plugin()
    assert len(out2) == 1
    assert out2 == [("hello", a2)]
示例#4
0
    def __init__(self, pluginmanager: PluginManager, file_type: str) -> None:
        self.file_type = file_type
        serializer_name = f"{SERIALIZER_PREFIX}{self.file_type}"
        importer_name = f"{IMPORTER_PREFIX}{self.file_type}"
        plugins = dict(pluginmanager.list_name_plugin())

        if serializer_name not in plugins and importer_name not in plugins:
            options = available_serializers(pluginmanager).union(
                available_importers(pluginmanager)
            )
            raise SerializationError(
                f"File type {file_type} not supported. You may"
                f" need to install a plugin supporting this type."
                f" Available types: {options}"
            )

        self._entry_serializer = (
            plugins[serializer_name]
            if serializer_name in plugins
            else plugins[importer_name]
        )
示例#5
0
class PluginManager(object):
    """
    A PluginManager class for scanning-related plugins.
    """

    # a global managers cache as a mapping of {stage: manager instance}
    managers = {}

    def __init__(self, stage, module_qname, entrypoint, plugin_base_class):
        """
        Initialize this plugin manager for the `stage` specified in the fully
        qualified Python module name `module_qname` with plugins loaded from the
        setuptools `entrypoint` that must subclass `plugin_base_class`.
        """
        self.manager = PluggyPluginManager(project_name=stage)
        self.managers[stage] = self

        self.stage = stage
        self.entrypoint = entrypoint
        self.plugin_base_class = plugin_base_class
        self.manager.add_hookspecs(sys.modules[module_qname])

        # set to True once this manager is initialized by running its setup()
        self.initialized = False

        # list of plugin_class for all the plugins of this manager
        self.plugin_classes = []

    @classmethod
    def load_plugins(cls):
        """
        Setup the plugins enviroment.
        Must be called once to initialize all the plugins of all managers.
        """
        plugin_classes = []
        plugin_options = []
        for stage, manager in cls.managers.items():
            mgr_setup = manager.setup()
            if not mgr_setup:
                msg = 'Cannot load plugins for stage: %(stage)s' % locals()
                raise PlugincodeError(msg)
            mplugin_classes, mplugin_options = mgr_setup
            plugin_classes.extend(mplugin_classes)
            plugin_options.extend(mplugin_options)
        return plugin_classes, plugin_options

    def setup(self):
        """
        Return a tuple of (list of all plugin classes, list of all options of
        all plugin classes).

        Load and validate available plugins for this PluginManager from its
        assigned `entrypoint`. Raise a PlugincodeError if a plugin is not valid such
        that when it does not subcclass the manager `plugin_base_class`.
        Must be called once to setup the plugins of this manager.
        """
        if self.initialized:
            return

        entrypoint = self.entrypoint
        try:
            self.manager.load_setuptools_entrypoints(entrypoint)
        except ImportError as e:
            raise e
        stage = self.stage

        plugin_options = []
        plugin_classes = []
        required_plugins = set()
        for name, plugin_class in self.manager.list_name_plugin():

            if not issubclass(plugin_class, self.plugin_base_class):
                qname = '%(stage)s:%(name)s' % locals()
                plugin_base_class = self.plugin_base_class
                raise PlugincodeError(
                    'Invalid plugin: %(qname)r: %(plugin_class)r '
                    'must extend %(plugin_base_class)r.' % locals())

            for option in plugin_class.options:
                if not isinstance(option, cliutils.PluggableCommandLineOption):
                    qname = '%(stage)s:%(name)s' % locals()
                    oname = option.name
                    clin = cliutils.PluggableCommandLineOption
                    raise PlugincodeError(
                        'Invalid plugin: %(qname)r: option %(oname)r '
                        'must extend %(clin)r.' % locals())
                plugin_options.append(option)

            plugin_class.stage = stage
            plugin_class.name = name

            plugin_classes.append(plugin_class)

        self.plugin_classes = sorted(plugin_classes,
                                     key=lambda c: (c.sort_order, c.name))
        self.initialized = True
        return self.plugin_classes, plugin_options