openalea.core.plugin package#
Subpackages#
Submodules#
openalea.core.plugin.functor module#
openalea.core.plugin.instance module#
- class openalea.core.plugin.instance.PluginInstanceManager(manager, plugins=None, proxy_class=None)[source]#
Bases:
object- property debug#
- instance(group, name, class_args=None, class_kwds=None)[source]#
Use this function if you always want the same instance: If plugin has never been called, create a new instance else return first created one.
- instances(group, name=None, class_args=None, class_kwds=None)[source]#
Return all existing instances corresponding to this plugin
- new(group, name, class_args=None, class_kwds=None)[source]#
Create a new instance and register it. You can get all created instances with instances method.
- openalea.core.plugin.instance.enhanced_error(error, **kwds)[source]#
Add plugin information to given exception. By default, if a plugin fails, for example because a dependency cannot be imported, user get error message “ImportError: No module named mydep”. This message is useless because we don’t know which plugin has failed.
Once enhanced, error message become: “MyLab (mypackage.lab.mylab): ImportError: No module named mydep”
kwds:
plugin: plugin instance
plugin_class: plugin class
openalea.core.plugin.interface module#
interface plugin documentation#
openalea.core.plugin.manager module#
This plugin manager is inspired by nose PluginManager(s) released under LGPL license. You can get a full copy of this license on nosetest repository:lgpl.txt You can get original nose code on github
Plugin Manager#
A plugin manager class is used to load plugins, search among it and manage the list of loaded plugins. Plugins are loaded from entry points or can be added dynamically to manager.
To list plugins, see
PluginManager.plugin()andPluginManager.plugins().To add plugins dynamically, see
PluginManager.add_plugin()andPluginManager.add_plugins().
All plugin are sorted in categories, each group defining a contract. This contract is generally described in an interface class or documentation.
If you want to use third party plugins that doesn’t fit perfectly to your contract,
you can embed its in plugin proxies.
To do that, you can specify a proxy class for an entire group or for one plugin.
See PluginManager.set_proxy() and “plugin_proxy” parameter in PluginManager.add_plugin().
- class openalea.core.plugin.manager.PluginManager(items=None, item_proxy=None, autoload=['entry_points'])[source]#
Bases:
GenericManager
openalea.core.plugin.node module#
openalea.core.plugin.plugin module#
- class openalea.core.plugin.plugin.IPlugin[source]#
Bases:
objectDefine a Plugin from an entry point.
- property distribution#
Current python distribution
- property identifier#
PluginClass
- Type:
Unique identifier. By default, identifier is pluginmodule
- property implementation#
Real implementation
- property label#
Human readable name
- property module#
Module containing implementation
- property modulename#
Python module path containing implementation
- property name#
Short name to identify plugin. Different plugin may have same name.
- property objectname#
Name of implementation
- class openalea.core.plugin.plugin.PluginDef(klass)[source]#
Bases:
object- DROP_PLUGIN = 1#
- LOWER_CASE = 2#
- UNCHANGED = 0#
Module contents#
- To define a new extension (ex: an applet called MyApplet) corresponding to a category (ex: oalab.applet), you must
write a Plugin class (ex: “PluginMyApplet”) that respects a special “IPlugin” interface (ex: IPluginApplet)
write or use a class that actually does the job (ex: MyApplet) that respects a special “interface” (ex: IApplet)
add it to the right “entry_point” (ex: oalab.applet)
Interfaces and entry_points are described in plugin documentation. Generally, a plugin code looks like:
1#filename: ex: mypackage/plugin/applet.py
2
3class PluginMyApplet(object):
4 name = 'MyApplet'
5 label = 'My Applet'
6 __plugin__ = True
7
8 def __call__(self):
9 from mypackage.gui.applet.myapplet import MyApplet
10 return MyApplet
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’).
Coding conventions#
In openalea packages, plugin follow this convention:
package.plugin.category#
- Describe how to extend this package:
entry point category supported by this package (generally “package.category”)
API of plugin class (required attributes, optional meta-info, …)
API of implementation (can be function or class)
Generally, API are described from documentation or interface classes.
ex: openalea.core.plugin.applet
package.plugin.builtin#
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
package.*#
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.