plugout

A simple plugin manager


License
Other
Install
pip install plugout==0.1.1

Documentation

Build Status PyPI PyPI Code Health Coverage Status

PlugOut

Plugout is a plugin manager for Python.

It's a common pattern to allow people to extend an application with plugins. Plugout lets you define a base class that can be derived looped back into your application.

Plugout was originally designed to allow visualization extensions to Caravel and plugins for Airflow.

Example

Now picture an application for image processing shotophot that can be extended with filter

class BaseFilterPlugin(object):
    def process(img):
        raise NotImplemented()

Now picture and external module that defines a filter

from shotophot import BaseFilterPlugin

class BlackWhitePlugin(BaseFilterPlugin):
    def process(img):
        return mutate(img)

Now your application can discover the objects provided externally.

from plugout import PluginManager
from shotophot import BaseFilterPlugin
from shotophot import conf

# Load a plugout plugin manager specifying the base class we are
# looking for derivatives from
pm = PluginManager(base_class=BaseSuperPlugin)

# where conf.get('PLUGIN_PATHS') is a user provided list of Python
# dotted reference as in `['package.module.ClassName']`, where
# ClassName is a derivative of BaseFilterPlugin
pm.load_from_dotted_paths(conf.get('PLUGIN_PATHS'))

pm.plugins  # A list of plugins classes that were found

You can also crawl through a folder/subfolders to discover derivatives of BaseSuperPlugin

# where conf.get('PLUGINS_FOLDER') is a file system reference
# as in `/var/lib/share/shotophot_plugins`
pm.load_from_filepath(conf.get('PLUGINS_FOLDER'))

In some cases, importing plugins can lead to circular dependencies, in that case you can reference a dotted object reference to a callable

# where conf.get('PLUGIN_CALLABLES') is a dotted Python reference to
# callables expected to return a derivative of BaseFilterPlugin
# Note that the callable you define will be passed base_class as the first
# argument
pm.load_from_callables(conf.get('PLUGIN_CALLABLES'))