HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Simple Python plugin loader

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pluginsimpleloaderpython

Problem

I have written a simple system to load plugins from files in Python 2.7, and I'd like to see if any of it can be improved upon.

vedo.py

from __future__ import absolute_import

import os.path
import inspect

from vedo.event_emitter import EventEmitter
from vedo import VedoPlugin

def _get_module_name(directory, filename):
    return '{0}.{1}'.format(os.path.basename(directory), filename)

def _is_plugin_class(plugin_class):
    return (inspect.isclass(plugin_class) and
            issubclass(plugin_class, VedoPlugin) and
            plugin_class != VedoPlugin)

class Vedo(EventEmitter):
    def __init__(self, plugin_directory):
        self._plugin_directory = plugin_directory
        self._plugins = []

    @property
    def plugin_directory(self):
        return self._plugin_directory

    @property
    def plugins(self):
        return self._plugins

    def load_module(self, module):
        plugin_classes = [c for c in module.__dict__.values() if
                          _is_plugin_class(c)]

        for plugin_class in plugin_classes:
            self.plugins.append(plugin_class(self))

    def load_file(self, name):
        try:
            plugin_module = _get_module_name(self._plugin_directory, name)
            namespace = __import__(plugin_module)
        except ImportError:
            return

        self.load_module(getattr(namespace, name))


Each plugin must inherit from VedoPlugin, and is loaded by the Vedo class.

Here's an example plugin:

plugins/first.py

class MyFirstPlugin(VedoPlugin):
    def __init__(self, vedo):
        super(MyFirstPlugin, self).__init__(vedo)


And a quick example of how to use Vedo:

vedo = Vedo("./plugins")
vedo.load_file("first")

vedo.plugins[0] # This is an instance of `MyFirstPlugin'


Here's some things I'm not too fond of, but I'm not sure what I can do about them:

  • Should the private functions in the top of vedo.py be moved inside the Vedo class?



  • Should load_module be private

Solution

Regarding your questions:

  • No, I think the functions as they are are fine, not everything needs


to be moved into a class.

  • If it's an implementation detail, sure.



  • AFAIK no, but if it's otherwise empty the method doesn't have to be


added.

Also:

-
In load_module the loop can be more compact by using a combination
of list.extend and filter.

def load_module(self, module):
self.plugins.extend(filter(_is_plugin_class,
module.__dict__.values()))


  • The numbered arguments for str.format could be left out.



Looks good otherwise. If you're really concerned with keeping the
internals safe you could also not expose the plugins list directly,
but provide a separate accessor instead.

Context

StackExchange Code Review Q#109464, answer score: 2

Revisions (0)

No revisions yet.