Yet Another Plugin SYstem — Yapsy 1.12.2 documentation (original) (raw)

A simple plugin system for Python applications

Quick links:

On this page

Overview

Yapsy’s main purpose is to offer a way to easily design a plugin system in Python, and motivated by the fact that many other Python plugin system are either too complicated for a basic use or depend on a lot of libraries. Yapsy only depends on Python’s standard library.

Yapsy basically defines two core classes:

Getting started

The basic classes defined by Yapsy should work “as is” and enable you to load and activate your plugins. So that the following code should get you a fully working plugin management system:

from yapsy.PluginManager import PluginManager

Build the manager

simplePluginManager = PluginManager()

Tell it the default place(s) where to find plugins

simplePluginManager.setPluginPlaces(["path/to/myplugins"])

Load all plugins

simplePluginManager.collectPlugins()

Activate all loaded plugins

for pluginInfo in simplePluginManager.getAllPlugins(): simplePluginManager.activatePluginByName(pluginInfo.name)

Note

The plugin_info object (typically an instance ofIPlugin) plays as the entry point of each plugin. That’s also where Yapsy ceases to guide you: it’s up to you to define what your plugins can do and how you want to talk to them ! Talking to your plugin will then look very much like the following:

Trigger 'some action' from the loaded plugins

for pluginInfo in simplePluginManager.getAllPlugins(): pluginInfo.plugin_object.doSomething(...)

yapsy. NormalizePluginNameForModuleName(pluginName)

Normalize a plugin name into a safer name for a module name.

Note

may do a little more modifications than strictly necessary and is not optimized for speed.

yapsy. PLUGIN_NAME_FORBIDEN_STRING = ';;'

Warning

This string (‘;;’ by default) is forbidden in plugin names, and will be usable to describe lists of plugins for instance (see ConfigurablePluginManager)

Make it your own

For applications that require the plugins and their managers to be more sophisticated, several techniques make such enhancement easy. The following sections detail the most frequent needs for extensions and what you can do about it.

More sophisticated plugin classes

You can define a plugin class with a richer interface thanIPlugin, so long as it inherits from IPlugin, it should work the same. The only thing you need to know is that the plugin instance is accessible via the PluginInfo instance from itsPluginInfo.plugin_object.

It is also possible to define a wider variety of plugins, by defining as much subclasses of IPlugin. But in such a case you have to inform the manager about that before collecting plugins:

Build the manager

simplePluginManager = PluginManager()

Tell it the default place(s) where to find plugins

simplePluginManager.setPluginPlaces(["path/to/myplugins"])

Define the various categories corresponding to the different

kinds of plugins you have defined

simplePluginManager.setCategoriesFilter({ "Playback" : IPlaybackPlugin, "SongInfo" : ISongInfoPlugin, "Visualization" : IVisualisation, })

Note

Communicating with the plugins belonging to a given category might then be achieved with some code looking like the following:

Trigger 'some action' from the "Visualization" plugins

for pluginInfo in simplePluginManager.getPluginsOfCategory("Visualization"): pluginInfo.plugin_object.doSomething(...)

Enhance the plugin manager’s interface

To make the plugin manager more helpful to the other components of an application, you should consider decorating it.

Actually a “template” for such decoration is provided asPluginManagerDecorator, which must be inherited in order to implement the right decorator for your application.

Such decorators can be chained, so that you can take advantage of the ready-made decorators such as:

ConfigurablePluginManager

Implements a PluginManager that uses a configuration file to save the plugins to be activated by default and also grants access to this file to the plugins.

AutoInstallPluginManager

Automatically copy the plugin files to the right plugin directory.

A full list of pre-implemented decorators is available at Built-in Extensions.

Modify plugin descriptions and detections

By default, plugins are described by a text file called the plugin “info file” expected to have a “.yapsy-plugin” extension.

You may want to use another way to describe and detect your application’s plugin and happily yapsy (since version 1.10) makes it possible to provide the PluginManager with a custom strategy for plugin detection.

See IPluginLocator for the required interface of such strategies and PluginFileLocator for a working example of such a detection strategy.

Modify the way plugins are loaded

To tweak the plugin loading phase it is highly advised to re-implement your own manager class.

The nice thing is, if your new manager inherits PluginManager, then it will naturally fit as the start point of any decoration chain. You just have to provide an instance of this new manager to the first decorators, like in the following:

build and configure a specific manager

baseManager = MyNewManager()

start decorating this manager to add some more responsibilities

myFirstDecorator = AFirstPluginManagerDecorator(baseManager)

add even more stuff

mySecondDecorator = ASecondPluginManagerDecorator(myFirstDecorator)

Note

Some decorators have been implemented that modify the way plugins are loaded, this is however not the easiest way to do it and it makes it harder to build a chain of decoration that would include these decorators. Among those areVersionedPluginManager andFilteredPluginManager

Development

Contributing or forking ?

You’re always welcome if you suggest any kind of enhancements, any new decorators or any new pluginmanager. Even more if there is some code coming with it though this is absolutely not compulsory.

It is also really fine to fork the code ! In the past, some people found Yapsy just good enough to be used as a “code base” for their own plugin system, which they evolved in a more or less incompatible way with the “original” Yapsy, if you think about it, with such a small library this is actually a clever thing to do.

In any case, please remember that just providing some feedback on where you’re using Yapsy (original or forked) and how it is useful to you, is in itself a appreciable contribution :)

License

The work is placed under the simplified BSD license in order to make it as easy as possible to be reused in other projects.

Please note that the icon is not under the same license but under theCreative Common Attribution-ShareAlike license.

Forge

The project is hosted by Sourceforge where you can access the code, documentation and a tracker to share your feedback and ask for support.

SourceForge.net

Any suggestion and help are much welcome !

Yapsy is also tested on the continous integration service TravisCI:Continuous integration tests Code coverage from continuous integration tests.

A few alternative sites are available:

References

Other Python plugin systems already existed before Yapsy and some have appeared after that. Yapsy’s creation is by no mean a sign that these others plugin systems sucks :) It is just the results of me being slighlty lazy and as I had already a good idea of how a simple plugin system should look like, I wanted to implement my own1.

1

All the more because it seems that my modest design ideas slightly differ from what has been done in other libraries.