patternpythonMinor
Simple Python plugin loader
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
Each plugin must inherit from
Here's an example plugin:
plugins/first.py
And a quick example of how to use Vedo:
Here's some things I'm not too fond of, but I'm not sure what I can do about them:
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.pybe moved inside theVedoclass?
- Should
load_modulebe private
Solution
Regarding your questions:
to be moved into a class.
added.
Also:
-
In
of
Looks good otherwise. If you're really concerned with keeping the
internals safe you could also not expose the
but provide a separate accessor instead.
- 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 combinationof
list.extend and filter.def load_module(self, module):
self.plugins.extend(filter(_is_plugin_class,
module.__dict__.values()))
- The numbered arguments for
str.formatcould 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.