openalea.core.plugin package#

Subpackages#

Submodules#

openalea.core.plugin.functor module#

class openalea.core.plugin.functor.PluginFunctor[source]#

Bases: object

static factory(group, default=None, *tags, **criteria)[source]#
property plugin#
openalea.core.plugin.functor.get_plugin(self)[source]#
openalea.core.plugin.functor.plugin_doc(plugin_func)[source]#
openalea.core.plugin.functor.set_plugin(self, name)[source]#

openalea.core.plugin.instance module#

class openalea.core.plugin.instance.PluginInstanceManager(manager, plugins=None, proxy_class=None)[source]#

Bases: object

clear()[source]#
property debug#
function(group, name)[source]#
has_instance(group, name)[source]#
implementations(interface, **kwds)[source]#

Return all instances implementing this interface

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.

register(group, name, instance)[source]#

Add a weakref to instance in dict group -> name -> [list of instances]

set_manager(manager)[source]#
unregister(group, name, instance)[source]#

Unregistered instances won’t be list by “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#

class openalea.core.plugin.interface.IPluginInterface[source]#

Bases: object

group of interfaces

interfaces = []#

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() and PluginManager.plugins().

  • To add plugins dynamically, see PluginManager.add_plugin() and PluginManager.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

discover(group=None, item_proxy=None)[source]#
generate_item_id(plugin)[source]#
classmethod generate_item_name(item)[source]#
instantiate(item)[source]#
patch_ep_plugin(plugin, ep)[source]#
patch_item(item)[source]#

openalea.core.plugin.node module#

openalea.core.plugin.node.node_factory(plugin_name, group=None, name=None, category=None)[source]#

openalea.core.plugin.plugin module#

class openalea.core.plugin.plugin.IPlugin[source]#

Bases: object

Define 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.Plugin[source]#

Bases: object

class openalea.core.plugin.plugin.PluginDef(klass)[source]#

Bases: object

DROP_PLUGIN = 1#
LOWER_CASE = 2#
UNCHANGED = 0#
openalea.core.plugin.plugin.discover(group, name=None)[source]#

Return all Plugin objects from group.

Parameters:
  • group : the name of a plugin group

Returns:
  • plugins : dict of name:plugin

Todo:

check that the same name is not used by several plugins

openalea.core.plugin.plugin.find_distribution(name)[source]#
openalea.core.plugin.plugin.iter_groups()[source]#
openalea.core.plugin.plugin.iter_plugins(group, name=None, debug=False)[source]#
openalea.core.plugin.plugin.plugin_name(plugin)[source]#

Module contents#

To define a new extension (ex: an applet called MyApplet) corresponding to a category (ex: oalab.applet), you must
  1. write a Plugin class (ex: “PluginMyApplet”) that respects a special “IPlugin” interface (ex: IPluginApplet)

  2. write or use a class that actually does the job (ex: MyApplet) that respects a special “interface” (ex: IApplet)

  3. 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.