This document explains how to concretely extend OpenAleaLab. For theoretical aspects and future plans, see PEP: Plugin management.
Plugins are used to extend application. All plugins are managed in the same way but can do really different tasks and have very different behaviour. For example an "image processing algorithm", a "qt applet" and an "OpenAleaLab extension" are all plugins, defined and registered in the same way but with very different logics. The logic and expected behaviour are described in an "interface" associated to a "category".
Plugin mechanism can be explained by this scheme:
Plugin category ‣ Plugin identifier ‣ Plugin (factory) ‣ Class
Plugin category: A plugin category gather all extension providing same feature (for example, an applet in GUI). This category is defined using entry_point group. It defines implicitly that all plugins in this category adhere to a common interface. See "Available entry points" to know matching between groups and interfaces.
Plugin identifier: A name and a path to identify and allow to load real plugin.
Plugin (factory): A simple class that describe component features. But, it is very important, that class must not import module or implement features. To get class implementing features, a special method called load can be used.
Class Class that actually implements features.
Some plugins are loaded automatically by application. For instance, it is the case for interfaces. Some other plugins are loaded only if ask for it. For exemple, if user want to edit a curve, interface may propose different editors and allow user to choose which one he prefers. In this case, only plugin chosen by user is really loaded.
For the second case, it is very important to keep a plugin light.
- Labs [oalab.lab] New laboratory based on OpenAleaLab
- Applets [oalab.applet] : Graphical component displayed in main window.
- Controls [oalab.qt_control, oalab.notebook_control]: Data editors and viewers
- Interfaces [oalab.interface]: Description of data types
- Imaging algorithms [openalea.image.*]: Imaging algorithms
Interfaces and entry_points are described in plugin documentation. Generally, a plugin code looks like:
Once this class has been written, just register it in the setup.py file of your python package.
entry_points={
'oalab.applet': [
'oalab.applet/mypackage = mypackage.plugin.applet', # read all plugins defined in this module ...
]
}
Note
You can also define a plugin explicitly with:
With mypackage.plugin.applet python module path (equivalent to 'mypackage/plugin/applet.py').
In openalea packages, plugin follow this convention:
Generally, API are described from documentation or interface classes.
This module contains Plugin class, describing plugins that extend package itself or another package. Generally, these plugin define "default" or "standard" implementation and algorithms (if extend package itself) or alternatives (if extends an other package). Real implementation (class, algo, ...) are generally defined in an other module with explicit name.
Builtin plugin for package itself can also be used, by contributors, as real example of how to create a new plugin.
ex: openalea.core.plugin.builtin.applet
You are free to put real implementation (class or algo) in the module of your choice. Implementation are classical python objects (except that its follow a special API), so you can put code where you want, like you will do for other libraries. Follow a special interface doesn't mean class is derivated from an interface, just is has same public attributes and same methods.
Generally, package.category.implementation_name fit well.
ex: openalea.oalab.applet.filebrowser
or with a more generic package name:
ex: openalea.oalab.widget.filebrowser
In all cases, this path is defined in plugin class and you don't need to remember were package is defined.
See PluginManager.