PluginManager

Role

The PluginManager loads plugins that enforce the Plugin Description Policy, and offers the most simple methods to activate and deactivate the plugins once they are loaded.

Note

It may also classify the plugins in various categories, but this behaviour is optional and if not specified elseway all plugins are stored in the same default category.

Note

It is often more useful to have the plugin manager behave like singleton, this functionality is provided by PluginManagerSingleton

Plugin Description Policy

When creating a PluginManager instance, one should provide it with a list of directories where plugins may be found. In each directory, a plugin should contain the following elements:

For a Standard plugin:

myplugin.yapsy-plugin

A plugin info file identical to the one previously described.

myplugin

A directory ontaining an actual Python plugin (ie with a __init__.py file that makes it importable). The upper namespace of the plugin should present a class inheriting the IPlugin interface (the same remarks apply here as in the previous case).

For a Single file plugin:

myplugin.yapsy-plugin

A plugin info file which is identified thanks to its extension, see the Plugin Info File Format to see what should be in this file.

The extension is customisable at the PluginManager’s instanciation, since one may usually prefer the extension to bear the application name.

myplugin.py

The source of the plugin. This file should at least define a class inheriting the IPlugin interface. This class will be instanciated at plugin loading and it will be notified the activation/deactivation events.

Plugin Info File Format

The plugin info file is a text file encoded in ASCII or UTF-8 and gathering, as its name suggests, some basic information about the plugin.

  • it gives crucial information needed to be able to load the plugin

  • it provides some documentation like information like the plugin author’s name and a short description fo the plugin functionality.

Here is an example of what such a file should contain:

[Core]
Name = My plugin Name
Module = the_name_of_the_pluginto_load_with_no_py_ending
   
[Documentation]
Description = What my plugin broadly does
Author = My very own name
Version = the_version_number_of_the_plugin
Website = My very own website

Note

From such plugin descriptions, the PluginManager will built its own representations of the plugins as instances of the PluginInfo class.

Changing the default behaviour

The default behaviour for locating and loading plugins can be changed using the various options exposed on the interface via getters.

The plugin detection, in particular, can be fully customized by settting a custom plugin locator. See IPluginLocator for more details on this.

Extensibility

Several mechanisms have been put up to help extending the basic functionalities of the proivided classes.

A few hints to help you extend those classes:

If the new functionalities do not overlap the ones already implemented, then they should be implemented as a Decorator class of the base plugin. This should be done by inheriting the PluginManagerDecorator.

If this previous way is not possible, then the functionalities should be added as a subclass of PluginManager.

Note

The first method is highly prefered since it makes it possible to have a more flexible design where one can pick several functionalities and litterally add them to get an object corresponding to one’s precise needs.

API

class yapsy.PluginManager.PluginManager(categories_filter=None, directories_list=None, plugin_info_ext=None, plugin_locator=None)

Manage several plugins by ordering them in categories.

The mechanism for searching and loading the plugins is already implemented in this class so that it can be used directly (hence it can be considered as a bit more than a mere interface)

The file describing a plugin must be written in the syntax compatible with Python’s ConfigParser module as in the Plugin Info File Format

About the __init__:

Initialize the mapping of the categories and set the list of directories where plugins may be. This can also be set by direct call the methods:

  • setCategoriesFilter for categories_filter

  • setPluginPlaces for directories_list

  • setPluginInfoExtension for plugin_info_ext

You may look at these function’s documentation for the meaning of each corresponding arguments.

activatePluginByName(name, category='Default')

Activate a plugin corresponding to a given category + name.

appendPluginCandidate(candidateTuple)

Append a new candidate to the list of plugins that should be loaded.

The candidate must be represented by the same tuple described in getPluginCandidates.

appendPluginToCategory(plugin, category_name)

Append a new plugin to the given category.

collectPlugins()

Walk through the plugins’ places and look for plugins. Then for each plugin candidate look for its category, load it and stores it in the appropriate slot of the category_mapping.

deactivatePluginByName(name, category='Default')

Desactivate a plugin corresponding to a given category + name.

getAllPlugins()

Return the list of all plugins (belonging to all categories).

getCategories()

Return the list of all categories.

getPluginByName(name, category='Default')

Get the plugin correspoding to a given category and name

getPluginCandidates()

Return the list of possible plugins.

Each possible plugin (ie a candidate) is described by a 3-uple: (info file path, python file path, plugin info instance)

getPluginInfoClass()

DEPRECATED(>1.9): directly control that with the IPluginLocator instance instead !

Get the class that holds PluginInfo.

getPluginLocator()

Grant direct access to the plugin locator.

getPluginsOf(**kwargs)

Returns a set of plugins whose properties match the named arguments provided here along with their correspoding values.

getPluginsOfCategory(category_name)

Return the list of all plugins belonging to a category.

instanciateElement(element)

DEPRECATED(>1.11): reimplement instead instanciateElementWithImportInfo !

Override this method to customize how plugins are instanciated.

Warning

This method is called only if instanciateElementWithImportInfo has not been reimplemented !

instanciateElementWithImportInfo(element, element_name, plugin_module_name, candidate_filepath)

Override this method to customize how plugins are instanciated.

Note

This methods recieves the ‘element’ that is a candidate as the plugin’s main file, but also enough information to reload its containing module and this element.

loadPlugins(callback=None, callback_after=None)

Load the candidate plugins that have been identified through a previous call to locatePlugins. For each plugin candidate look for its category, load it and store it in the appropriate slot of the category_mapping.

You can specify 2 callbacks: callback, and callback_after. If either of these are passed a function, (in the case of callback), it will get called before each plugin load attempt and (for callback_after), after each attempt. The plugin_info instance is passed as an argument to each callback. This is meant to facilitate code that needs to run for each plugin, such as adding the directory it resides in to sys.path (so imports of other files in the plugin’s directory work correctly). You can use callback_after to remove anything you added to the path.

locatePlugins()

Convenience method (actually call the IPluginLocator method)

removePluginCandidate(candidateTuple)

Remove a given candidate from the list of plugins that should be loaded.

The candidate must be represented by the same tuple described in getPluginCandidates.

removePluginFromCategory(plugin, category_name)

Remove a plugin from the category where it’s assumed to belong.

setCategoriesFilter(categories_filter)

Set the categories of plugins to be looked for as well as the way to recognise them.

The categories_filter first defines the various categories in which the plugins will be stored via its keys and it also defines the interface tha has to be inherited by the actual plugin class belonging to each category.

setPluginInfoClass(picls, strategies=None)

DEPRECATED(>1.9): directly configure the IPluginLocator instance instead !

Convenience method (actually call self.getPluginLocator().setPluginInfoClass)

When using a PluginFileLocator you may restrict the strategies to which the change of PluginInfo class will occur by just giving the list of strategy names in the argument “strategies”

setPluginInfoExtension(ext)

DEPRECATED(>1.9): for backward compatibility. Directly configure the IPluginLocator instance instead !

Warning

This will only work if the strategy “info_ext” is active for locating plugins.

setPluginLocator(plugin_locator, dir_list=None, picls=None)

Sets the strategy used to locate the basic information.

See IPluginLocator for the policy that plugin_locator must enforce.

setPluginPlaces(directories_list)

DEPRECATED(>1.9): directly configure the IPluginLocator instance instead !

Convenience method (actually call the IPluginLocator method)

updatePluginPlaces(directories_list)

DEPRECATED(>1.9): directly configure the IPluginLocator instance instead !

Convenience method (actually call the IPluginLocator method)

class yapsy.PluginManager.PluginManagerSingleton

Singleton version of the most basic plugin manager.

Being a singleton, this class should not be initialised explicitly and the get classmethod must be called instead.

To call one of this class’s methods you have to use the get method in the following way: PluginManagerSingleton.get().themethodname(theargs)

To set up the various coonfigurables variables of the PluginManager’s behaviour please call explicitly the following methods:

  • setCategoriesFilter for categories_filter

  • setPluginPlaces for directories_list

  • setPluginInfoExtension for plugin_info_ext

classmethod get()

Actually create an instance

classmethod setBehaviour(list_of_pmd)

Set the functionalities handled by the plugin manager by giving a list of PluginManager decorators.

This function shouldn’t be called several time in a same process, but if it is only the first call will have an effect.

It also has an effect only if called before the initialisation of the singleton.

In cases where the function is indeed going to change anything the True value is return, in all other cases, the False value is returned.