Beispiel #1
0
def test_not_all_arguments_are_provided_issues_a_warning(
        pm: PluginManager) -> None:
    """Calling a hook without providing all arguments specified in
    the hook spec issues a warning."""
    class Spec:
        @hookspec
        def hello(self, arg1, arg2):
            pass

        @hookspec(historic=True)
        def herstory(self, arg1, arg2):
            pass

    pm.add_hookspecs(Spec)

    with pytest.warns(UserWarning,
                      match=r"'arg1', 'arg2'.*cannot be found.*$"):
        pm.hook.hello()
    with pytest.warns(UserWarning, match=r"'arg2'.*cannot be found.*$"):
        pm.hook.hello(arg1=1)
    with pytest.warns(UserWarning, match=r"'arg1'.*cannot be found.*$"):
        pm.hook.hello(arg2=2)

    with pytest.warns(UserWarning,
                      match=r"'arg1', 'arg2'.*cannot be found.*$"):
        pm.hook.hello.call_extra([], kwargs=dict())

    with pytest.warns(UserWarning,
                      match=r"'arg1', 'arg2'.*cannot be found.*$"):
        pm.hook.herstory.call_historic(kwargs=dict())
Beispiel #2
0
def test_opt_in_args(pm: PluginManager) -> None:
    """Verify that two hookimpls with mutex args can serve
    under the same spec.
    """
    class Api:
        @hookspec
        def hello(self, arg1, arg2, common_arg):
            "api hook 1"

    class Plugin1:
        @hookimpl
        def hello(self, arg1, common_arg):
            return arg1 + common_arg

    class Plugin2:
        @hookimpl
        def hello(self, arg2, common_arg):
            return arg2 + common_arg

    pm.add_hookspecs(Api)
    pm.register(Plugin1())
    pm.register(Plugin2())

    results = pm.hook.hello(arg1=1, arg2=2, common_arg=0)
    assert results == [2, 1]
Beispiel #3
0
def get_serializers(refresh_cache=False):
    """Discover and return Serializer classes from all installed plugins

    Serializers are cached and are not repeatedly loaded in future calls

    Args:
        refresh_cache (bool): If True, ignore any existing serializer cache and discover serializers as normal

    Returns:
        dict: Keys are the formats provided by and pointing to their respective Serializers
    """
    global _serializer_cache

    if _serializer_cache is None or refresh_cache:
        from pluggy import PluginManager

        package_name = __name__.split('.')[0]
        pm = PluginManager(package_name)
        pm.load_setuptools_entrypoints(package_name + '.serializers')

        for mod in pm.get_plugins():
            import_submodules(mod)

        _serializer_cache = {}

        for serializer_class in get_recursive_subclasses(Serializer):
            if not serializer_class.format:
                logger.warning(
                    'Serializer "{}" does not provide a format, will not be auto-discovered'
                    .format(get_full_qualname(serializer_class)))
                continue

            _serializer_cache[serializer_class.format] = serializer_class

    return _serializer_cache
Beispiel #4
0
def test_hook_tracing(he_pm: PluginManager) -> None:
    saveindent = []

    class api1:
        @hookimpl
        def he_method1(self):
            saveindent.append(he_pm.trace.root.indent)

    class api2:
        @hookimpl
        def he_method1(self):
            saveindent.append(he_pm.trace.root.indent)
            raise ValueError()

    he_pm.register(api1())
    out: List[Any] = []
    he_pm.trace.root.setwriter(out.append)
    undo = he_pm.enable_tracing()
    try:
        indent = he_pm.trace.root.indent
        he_pm.hook.he_method1(arg=1)
        assert indent == he_pm.trace.root.indent
        assert len(out) == 2
        assert "he_method1" in out[0]
        assert "finish" in out[1]

        out[:] = []
        he_pm.register(api2())

        with pytest.raises(ValueError):
            he_pm.hook.he_method1(arg=1)
        assert he_pm.trace.root.indent == indent
        assert saveindent[0] > indent
    finally:
        undo()
Beispiel #5
0
def test_load_setuptools_instantiation(monkeypatch, pm: PluginManager) -> None:
    class EntryPoint:
        name = "myname"
        group = "hello"
        value = "myname:foo"

        def load(self):
            class PseudoPlugin:
                x = 42

            return PseudoPlugin()

    class Distribution:
        entry_points = (EntryPoint(), )

    dist = Distribution()

    def my_distributions():
        return (dist, )

    monkeypatch.setattr(importlib_metadata, "distributions", my_distributions)
    num = pm.load_setuptools_entrypoints("hello")
    assert num == 1
    plugin = pm.get_plugin("myname")
    assert plugin is not None
    assert plugin.x == 42
    ret = pm.list_plugin_distinfo()
    # poor man's `assert ret == [(plugin, mock.ANY)]`
    assert len(ret) == 1
    assert len(ret[0]) == 2
    assert ret[0][0] == plugin
    assert ret[0][1]._dist == dist  # type: ignore[comparison-overlap]
    num = pm.load_setuptools_entrypoints("hello")
    assert num == 0  # no plugin loaded by this call
Beispiel #6
0
def test_warning_on_call_vs_hookspec_arg_mismatch():
    """Verify that is a hook is called with less arguments then defined in the
    spec that a warning is emitted.
    """
    class Spec:
        @hookspec
        def myhook(self, arg1, arg2):
            pass

    class Plugin:
        @hookimpl
        def myhook(self, arg1):
            pass

    pm = PluginManager(hookspec.project_name)
    pm.register(Plugin())
    pm.add_hookspecs(Spec())

    with warnings.catch_warnings(record=True) as warns:
        warnings.simplefilter('always')

        # calling should trigger a warning
        pm.hook.myhook(arg1=1)

        assert len(warns) == 1
        warning = warns[-1]
        assert issubclass(warning.category, Warning)
        assert "Argument(s) ('arg2',)" in str(warning.message)
Beispiel #7
0
def hc(pm: PluginManager) -> _HookCaller:
    class Hooks:
        @hookspec
        def he_method1(self, arg: object) -> None:
            pass

    pm.add_hookspecs(Hooks)
    return pm.hook.he_method1
Beispiel #8
0
def test_has_plugin(pm: PluginManager) -> None:
    class A:
        pass

    a1 = A()
    pm.register(a1, "hello")
    assert pm.is_registered(a1)
    assert pm.has_plugin("hello")
Beispiel #9
0
def test_prefix_hookimpl_dontmatch_module():
    with pytest.deprecated_call():
        pm = PluginManager(hookspec.project_name, "hello_")

    class BadPlugin(object):
        hello_module = __import__("email")

    pm.register(BadPlugin())
    pm.check_pending()
Beispiel #10
0
    def test_only_kwargs(self):
        pm = PluginManager("he")

        class Api:
            def hello(self, arg):
                "api hook 1"

        pm.addhooks(Api)
        pytest.raises(TypeError, lambda: pm.hook.hello(3))
Beispiel #11
0
    def test_only_kwargs(self):
        pm = PluginManager("he")

        class Api:
            def hello(self, arg):
                "api hook 1"

        pm.addhooks(Api)
        pytest.raises(TypeError, lambda: pm.hook.hello(3))
Beispiel #12
0
def _create_hook_manager() -> PluginManager:
    """Create a new PluginManager instance and register Kedro's hook specs.
    """
    manager = PluginManager(HOOK_NAMESPACE)
    manager.add_hookspecs(NodeSpecs)
    manager.add_hookspecs(PipelineSpecs)
    manager.add_hookspecs(DataCatalogSpecs)
    manager.add_hookspecs(RegistrationSpecs)
    return manager
Beispiel #13
0
def test_register_dynamic_attr(he_pm: PluginManager) -> None:
    class A:
        def __getattr__(self, name):
            if name[0] != "_":
                return 42
            raise AttributeError()

    a = A()
    he_pm.register(a)
    assert not he_pm.get_hookcallers(a)
Beispiel #14
0
def he_pm(request, pm: PluginManager) -> PluginManager:
    hookspec = HookspecMarker("example")

    class Hooks:
        @hookspec
        def he_method1(self, arg: int) -> int:
            return arg + 1

    pm.add_hookspecs(request.param(Hooks))
    return pm
Beispiel #15
0
def test_implprefix_deprecated():
    with pytest.deprecated_call():
        pm = PluginManager('blah', implprefix='blah_')

    class Plugin:
        def blah_myhook(self, arg1):
            return arg1

    with pytest.deprecated_call():
        pm.register(Plugin())
Beispiel #16
0
def test_implprefix_deprecated():
    with pytest.deprecated_call():
        pm = PluginManager("blah", implprefix="blah_")

    class Plugin:
        def blah_myhook(self, arg1):
            return arg1

    with pytest.deprecated_call():
        pm.register(Plugin())
Beispiel #17
0
def test_historic_with_subset_hook_caller(pm: PluginManager) -> None:
    class Hooks:
        @hookspec(historic=True)
        def he_method1(self, arg):
            ...

    pm.add_hookspecs(Hooks)

    out = []

    class Plugin:
        @hookimpl
        def he_method1(self, arg):
            out.append(arg)

    plugin = Plugin()
    pm.register(plugin)

    class Plugin2:
        @hookimpl
        def he_method1(self, arg):
            out.append(arg * 10)

    shc = pm.subset_hook_caller("he_method1", remove_plugins=[plugin])
    shc.call_historic(kwargs=dict(arg=1))

    pm.register(Plugin2())
    assert out == [10]

    pm.register(Plugin())
    assert out == [10, 1]
Beispiel #18
0
def test_register_mismatch_arg(he_pm: PluginManager) -> None:
    class hello:
        @hookimpl
        def he_method1(self, qlwkje):
            pass

    plugin = hello()

    with pytest.raises(PluginValidationError) as excinfo:
        he_pm.register(plugin)
    assert excinfo.value.plugin is plugin
Beispiel #19
0
 def __init__(self, driver, timeout, pm=None):
     self.driver = driver
     self.driver_adapter = IDriver(driver)
     self.timeout = timeout
     self.pm = pm
     if self.pm is None:
         self.pm = PluginManager("pypom", implprefix="pypom_")
         self.pm.add_hookspecs(hooks)
         self.pm.load_setuptools_entrypoints("pypom.plugin")
         self.pm.check_pending()
     self.wait = self.driver_adapter.wait_factory(self.timeout)
Beispiel #20
0
    def _load_spec(self, event_dispatcher: pluggy.PluginManager) -> None:
        """
        Load all hookspec modules
        """

        # INFO - G.M - 2019-11-28 - get all submodules recursively,
        # find those with with hookspec suffix, import them and add them
        # to valid hookspec
        for hookspec_module_path in self.get_all_hookspec_module_path():
            module = importlib.import_module(hookspec_module_path)
            event_dispatcher.add_hookspecs(module)
Beispiel #21
0
def test_firstresult_no_plugin(pm: PluginManager) -> None:
    """If no implementations/plugins have been registered for a firstresult
    hook the multi-call loop should return a None value.
    """
    class Api:
        @hookspec(firstresult=True)
        def hello(self, arg):
            "api hook 1"

    pm.add_hookspecs(Api)
    res = pm.hook.hello(arg=3)
    assert res is None
Beispiel #22
0
def test_repr() -> None:
    class Plugin:
        @hookimpl
        def myhook(self):
            raise NotImplementedError()

    pm = PluginManager(hookspec.project_name)

    plugin = Plugin()
    pname = pm.register(plugin)
    assert repr(pm.hook.myhook.get_hookimpls()[0]) == (
        f"<HookImpl plugin_name={pname!r}, plugin={plugin!r}>")
Beispiel #23
0
def test_repr():
    class Plugin:
        @hookimpl
        def myhook(self):
            raise NotImplementedError()

    pm = PluginManager(hookspec.project_name)

    plugin = Plugin()
    pname = pm.register(plugin)
    assert repr(pm.hook.myhook._nonwrappers[0]) == (
        "<HookImpl plugin_name=%r, plugin=%r>" % (pname, plugin))
Beispiel #24
0
def test_register_mismatch_method(he_pm: PluginManager) -> None:
    class hello:
        @hookimpl
        def he_method_notexists(self):
            pass

    plugin = hello()

    he_pm.register(plugin)
    with pytest.raises(PluginValidationError) as excinfo:
        he_pm.check_pending()
    assert excinfo.value.plugin is plugin
Beispiel #25
0
def test_only_kwargs(pm: PluginManager) -> None:
    class Api:
        @hookspec
        def hello(self, arg):
            "api hook 1"

    pm.add_hookspecs(Api)
    with pytest.raises(TypeError) as exc:
        pm.hook.hello(3)  # type: ignore[call-arg]

    message = "__call__() takes 1 positional argument but 2 were given"
    assert message in str(exc.value)
Beispiel #26
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()
Beispiel #27
0
def get_pluginmanager(config, load_entry_points=True):
    pm = PluginManager("devpiweb")
    # support old plugins, but emit deprecation warnings
    pm._implprefix = "devpiweb_"
    pm.add_hookspecs(hookspecs)
    if load_entry_points:
        pm.load_setuptools_entrypoints("devpi_web")
    pm.check_pending()
    return pm
Beispiel #28
0
def test_repr():
    class Plugin:
        @hookimpl
        def myhook():
            raise NotImplementedError()

    pm = PluginManager(hookspec.project_name)

    plugin = Plugin()
    pname = pm.register(plugin)
    assert repr(pm.hook.myhook._nonwrappers[0]) == (
        "<HookImpl plugin_name=%r, plugin=%r>" % (pname, plugin)
    )
Beispiel #29
0
def test_call_extra(pm: PluginManager) -> None:
    class Hooks:
        @hookspec
        def he_method1(self, arg):
            pass

    pm.add_hookspecs(Hooks)

    def he_method1(arg):
        return arg * 10

    out = pm.hook.he_method1.call_extra([he_method1], dict(arg=1))
    assert out == [10]
Beispiel #30
0
def test_register_hookwrapper_not_a_generator_function(
        he_pm: PluginManager) -> None:
    class hello:
        @hookimpl(hookwrapper=True)
        def he_method1(self):
            pass  # pragma: no cover

    plugin = hello()

    with pytest.raises(PluginValidationError,
                       match="generator function") as excinfo:
        he_pm.register(plugin)
    assert excinfo.value.plugin is plugin
Beispiel #31
0
def test_no_hookspec(pm: PluginManager) -> None:
    """A hook with hookimpls can still be called even if no hookspec
    was registered for it (and call_pending wasn't called to check
    against it).
    """
    class Plugin:
        @hookimpl
        def hello(self, arg):
            return "Plugin.hello"

    pm.register(Plugin())

    assert pm.hook.hello(arg=10, extra=20) == ["Plugin.hello"]
Beispiel #32
0
def get_pluginmanager(load_entrypoints=True):
    pm = PluginManager("devpiserver")
    # support old plugins, but emit deprecation warnings
    pm._implprefix = "devpiserver_"
    pm.add_hookspecs(hookspecs)
    # XXX load internal plugins here
    if load_entrypoints:
        pm.load_setuptools_entrypoints("devpi_server")
    pm.check_pending()
    return pm
Beispiel #33
0
def get_pluginmanager(load_entry_points=True):
    pm = PluginManager("devpiclient", implprefix="devpiclient_")
    pm.add_hookspecs(hookspecs)
    if load_entry_points:
        pm.load_setuptools_entrypoints("devpi_client")
    pm.check_pending()
    return pm
Beispiel #34
0
def _register_hooks(hook_manager: PluginManager, hooks: Iterable[Any]) -> None:
    """Register all hooks as specified in ``hooks`` with the global ``hook_manager``.

    Args:
        hook_manager: Hook manager instance to register the hooks with.
        hooks: Hooks that need to be registered.

    """
    for hooks_collection in hooks:
        # Sometimes users might call hook registration more than once, in which
        # case hooks have already been registered, so we perform a simple check
        # here to avoid an error being raised and break user's workflow.
        if not hook_manager.is_registered(hooks_collection):
            hook_manager.register(hooks_collection)
Beispiel #35
0
    def test_argmismatch(self):
        class Api:
            def hello(self, arg):
                "api hook 1"
        pm = PluginManager("he")
        pm.addhooks(Api)

        class Plugin:
            def hello(self, argwrong):
                pass

        with pytest.raises(PluginValidationError) as exc:
            pm.register(Plugin())
        assert "argwrong" in str(exc.value)
Beispiel #36
0
def test_hookrelay_registration_by_specname_raises(pm: PluginManager) -> None:
    """Verify using specname still raises the types of errors during registration as it
    would have without using specname."""
    class Api:
        @hookspec
        def hello(self, arg: object) -> None:
            "api hook 1"

    pm.add_hookspecs(Api)

    # make sure a bad signature still raises an error when using specname
    class Plugin:
        @hookimpl(specname="hello")
        def foo(self, arg: int, too, many, args) -> int:
            return arg + 1

    with pytest.raises(PluginValidationError):
        pm.register(Plugin())

    # make sure check_pending still fails if specname doesn't have a
    # corresponding spec.  EVEN if the function name matches one.
    class Plugin2:
        @hookimpl(specname="bar")
        def hello(self, arg: int) -> int:
            return arg + 1

    pm.register(Plugin2())
    with pytest.raises(PluginValidationError):
        pm.check_pending()
Beispiel #37
0
    def test_firstresult_definition(self):
        class Api:
            def hello(self, arg):
                "api hook 1"
            hello.firstresult = True
        pm = PluginManager("he")
        pm.addhooks(Api)

        class Plugin:
            def hello(self, arg):
                return arg + 1

        pm.register(Plugin())
        res = pm.hook.hello(arg=3)
        assert res == 4
Beispiel #38
0
 def parse_hookimpl_opts(self, module_or_class, name):
     opts = PluginManager.parse_hookimpl_opts(
         self, module_or_class, name)
     if opts is None:
         if name.startswith("x1"):
             opts = {}
     return opts
Beispiel #39
0
def get_pluginmanager(load_entry_points=True):
    pm = PluginManager("devpipasswdreset", implprefix="devpipasswdreset_")
    pm.add_hookspecs(hookspecs)
    if load_entry_points:
        pm.load_setuptools_entrypoints("devpi_passwd_reset")
    pm.check_pending()
    return pm
Beispiel #40
0
def get_pluginmanager():
    pm = PluginManager("devpiserver", implprefix="devpiserver_")
    pm.add_hookspecs(hookspecs)
    # XXX load internal plugins here
    pm.load_setuptools_entrypoints("devpi_server")
    pm.check_pending()
    return pm
def get_pluggin_manager(load_entrypoints=True):
    pm = PluginManager('banana', implprefix='banana_')
    pm.add_hookspecs(hookspecs)
    if load_entrypoints:
        pm.load_setuptools_entrypoints('banana')
    pm.check_pending()
    return pm
Beispiel #42
0
    def test_prefix_hookimpl(self):
        pm = PluginManager(hookspec.project_name, "hello_")

        class HookSpec:
            @hookspec
            def hello_myhook(self, arg1):
                """ add to arg1 """

        pm.add_hookspecs(HookSpec)

        class Plugin:
            def hello_myhook(self, arg1):
                return arg1 + 1

        pm.register(Plugin())
        pm.register(Plugin())
        results = pm.hook.hello_myhook(arg1=17)
        assert results == [18, 18]
Beispiel #43
0
def test_plugin_getattr_raises_errors():
    """Pluggy must be able to handle plugins which raise weird exceptions
    when getattr() gets called (#11).
    """
    class DontTouchMe(object):
        def __getattr__(self, x):
            raise Exception('cant touch me')

    class Module(object):
        pass

    module = Module()
    module.x = DontTouchMe()

    pm = PluginManager(hookspec.project_name)
    # register() would raise an error
    pm.register(module, 'donttouch')
    assert pm.get_plugin('donttouch') is module
Beispiel #44
0
def test_prefix_hookimpl(include_hookspec):
    with pytest.deprecated_call():
        pm = PluginManager(hookspec.project_name, "hello_")

    if include_hookspec:

        class HookSpec(object):
            @hookspec
            def hello_myhook(self, arg1):
                """ add to arg1 """

        pm.add_hookspecs(HookSpec)

    class Plugin(object):
        def hello_myhook(self, arg1):
            return arg1 + 1

    with pytest.deprecated_call():
        pm.register(Plugin())
        pm.register(Plugin())
    results = pm.hook.hello_myhook(arg1=17)
    assert results == [18, 18]
Beispiel #45
0
def test_warn_when_deprecated_specified(recwarn):
    warning = DeprecationWarning("foo is deprecated")

    class Spec(object):
        @hookspec(warn_on_impl=warning)
        def foo(self):
            pass

    class Plugin(object):
        @hookimpl
        def foo(self):
            pass

    pm = PluginManager(hookspec.project_name)
    pm.add_hookspecs(Spec)

    with pytest.warns(DeprecationWarning) as records:
        pm.register(Plugin())
    (record,) = records
    assert record.message is warning
    assert record.filename == Plugin.foo.__code__.co_filename
    assert record.lineno == Plugin.foo.__code__.co_firstlineno
Beispiel #46
0
    def test_hapmypath(self):
        class Api:
            def hello(self, arg):
                "api hook 1"
        pm = PluginManager("he")
        pm.addhooks(Api)
        hook = pm.hook
        assert hasattr(hook, 'hello')
        assert repr(hook.hello).find("hello") != -1

        class Plugin:
            def hello(self, arg):
                return arg + 1

        plugin = Plugin()
        pm.register(plugin)
        l = hook.hello(arg=3)
        assert l == [4]
        assert not hasattr(hook, 'world')
        pm.unregister(plugin)
        assert hook.hello(arg=3) == []
Beispiel #47
0
from pluggy import PluginManager
from . import hookspec, PROJECT_NAME


# TODO: move to main?

manager = PluginManager(PROJECT_NAME)
manager.add_hookspecs(hookspec)
manager.load_setuptools_entrypoints('gumby.plugin')
Beispiel #48
0
    the --format command line option.
    Parameters:
     - `file_count`: the number of files and directories scanned.
     - `version`: ScanCode version
     - `notice`: ScanCode notice
     - `scanned_files`: an iterable of scan results for each file
     - `options`: a mapping of key by command line option to a flag True
        if this option was enabled.
     - `input`: the original input path scanned.
     - `output_file`: an opened, file-like object to write the output to.
     - `_echo`: a funtion to echo strings to stderr. This will be removedd in the future.
    """
    pass


output_plugins = PluginManager('scan_output_writer')
output_plugins.add_hookspecs(sys.modules[__name__])


def initialize():
    """
    NOTE: this defines the entry points for use in setup.py
    """
    output_plugins.load_setuptools_entrypoints('scancode_output_writers')


def get_format_plugins():
    """
    Return an ordered mapping of format name --> plugin callable for all
    the output plugins. The mapping is ordered by sorted key.
    This is the main API for other code to access format plugins.
post_scan_spec = HookspecMarker('post_scan')
post_scan_impl = HookimplMarker('post_scan')


@post_scan_spec
def post_scan_handler(active_scans, results):
    """
    Process the scanned files and yield the modified results.
    Parameters:
     - `active_scans`: a list of scanners names requested in the current run.
     - `results`: an iterable of scan results for each file or directory.
    """
    pass


post_scan_plugins = PluginManager('post_scan')
post_scan_plugins.add_hookspecs(sys.modules[__name__])


def initialize():
    """
    NOTE: this defines the entry points for use in setup.py
    """
    post_scan_plugins.load_setuptools_entrypoints('scancode_post_scan')


def get_post_scan_plugins():
    """
    Return an ordered mapping of
        "command line option name" --> "plugin callable"
    for all the post_scan plugins. The mapping is sorted by option name.