Yapsy: a simple hack to get rid of the plugin info file
I would like to use a plugin in my code. I searched for simple (but powerful) python modules and found Yapsy (among others).
This is what I was looking for, but the way Yapsy detects plugins is not very flexible and requires a plugin info file. I would like to get rid of it, without having to unwrap the code (if I start relying on Yapsy, I want to make sure that I get all the updates from it without having to recycle it every time).
I came out with this quick and dirty solution, which works great but does not improve the flexibility of the "discovery" process:
#!/usr/bin/env python
import os
import logging
from cStringIO import StringIO
from yapsy.PluginManager import PluginManager
from yapsy.IPlugin import IPlugin
from yapsy.PluginInfo import PluginInfo
class MyPluginManager(PluginManager):
"""
My attempt to get rid of the plugin info file...
"""
def __init__(self,
categories_filter={"Default":IPlugin},
directories_list=None,
plugin_info_ext="plugin.py"):
"""
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 documentation for the meaning
of each corresponding arguments.
"""
self.setPluginInfoClass(PluginInfo)
self.setCategoriesFilter(categories_filter)
self.setPluginPlaces(directories_list)
self.setPluginInfoExtension(plugin_info_ext)
def _gatherCorePluginInfo(self, directory, filename):
"""
Gather the core information (name, and module to be loaded)
about a plugin described by it info file (found at
'directory/filename').
Return an instance of ``self.plugin_info_cls`` and the
config_parser used to gather the core data *in a tuple*, if the
required info could be localised, else return ``(None,None)``.
.. note:: This is supposed to be used internally by subclasses
and decorators.
"""
# now we can consider the file as a serious candidate
candidate_infofile = os.path.join(directory,filename)
print candidate_infofile
# My hack : just create a StringIO file with basic plugin info
_fname = filename.rstrip(".py")
_file = StringIO()
_file.write("""[Core]
Name = %s
Module = %s
""" % (_fname, _fname))
_file.seek(0)
# parse the information file to get info about the plugin
name,moduleName,config_parser = self._getPluginNameAndModuleFromStream(_file, candidate_infofile)
print name, moduleName, config_parser
if (name,moduleName,config_parser)==(None,None,None):
return (None,None)
# start collecting essential info
plugin_info = self._plugin_info_cls(name,os.path.join(directory,moduleName))
return (plugin_info,config_parser)
This hack assumes that the plugin has a ".plugin.py" extension (or ".plugin" for a directory, but I haven't tested it). Then I create a cSringIO file to trick Yapsy into thinking he found the plugin info file. (It is still possible to provide additional information in the plugin by setting the correct variables: author, description ...).
I'm wondering if there is a better way or if people have already done this. This hack is clearly too crude to be really useful, and I would like to have something a little more flexible: a plugin can be detected by its plugin info file (as in the source code) or a pattern for the plugin name (perhaps using re
, which allows the prefix , suffix ...). As far as I can see, implementing these ideas would require a much more complex hack than what I have already done ...
source to share