Plugins

This section describes how plugins can be developed as stand-alone packages in order to extend the functionality of Kadi4Mat without having to touch the main application code. As currently all first-party plugins are part of the main application package, all existing examples can be found in the kadi.plugins module. This also includes code not implemented as a separate plugin, but still using the plugin hooks.

Plugin infrastructure

The plugin infrastructure in Kadi4Mat builds upon pluggy, a simple and flexible plugin system. It allows implementing different plugin interface functions, called hook specifications, which a plugin can choose to implement. Each hook will be called in certain places in the application flow, which will invoke all corresponding implementations of that hook.

In order for the main application to find a plugin, the plugin has to register itself using the kadi_plugins entry point, as also done for all first-party plugins in pyproject.toml. Each plugin needs to specify a unique name and the module that contains all hook implementations, according to the plugin’s corresponding build system configuration:

[project]
dependencies = [
    "kadi>=X,<Y",
]

[project.entry-points.kadi_plugins]
example = "kadi_plugin_example.plugin"
[options]
install_requires =
    kadi>=X,<Y

[options.entry_points]
kadi_plugins =
    example = kadi_plugin_example.plugin
from setuptools import setup

setup(
    install_requires=[
        "kadi>=X,<Y",
    ],
    entry_points={
        "kadi_plugins": [
            "example=kadi_plugin_example.plugin",
        ],
    },
)

In this example, the plugin is called example, while the hook implementations are loaded via the kadi_plugin_example.plugin module of a package called kadi_plugin_example.

Note

Whenever performing changes in the entry points while developing, it may be necessary to reinstall the application and/or any plugin packages in order to fully propagate the changes.

Plugin hooks

Plugin hooks can be implemented by using the hookimpl decorator. The name of the decorated function must correspond to the respective plugin hook. Plugin configurations, specified via the PLUGIN_CONFIG configuration value, can be loaded by using the get_plugin_config function (see also how to install plugins). An example implementation could look like the following:

from kadi.plugins import get_plugin_config
from kadi.plugins import hookimpl

@hookimpl
def kadi_example_plugin_hook():
    # Load the configuration of the "example" plugin, if necessary.
    config = get_plugin_config("example")
    # Validate the configuration or do something else with it.

To see a list of all currently existing hook specifications, please refer to the API reference.

Warning

As long as Kadi4Mat is still in beta, hook specifications are still subject to change without a guarantee of prior deprecation.

Plugin API

As plugins might need to make use of some of Kadi4Mat’s internal functionality in order to properly implement any hooks, a subset of the most relevant functions, classes and modules that a plugin might want to use are available via the kadi.plugins module, as also shown in the example above and listed in kadi/plugins/__init__.py. This module defines the public API that third-party plugins may use without fear of unexpected breaking changes.

Warning

As long as Kadi4Mat is still in beta, the public plugin API is still subject to change without a guarantee of prior deprecation.