Trivial plugin framework?

Jeremy Jones zanesdad at bellsouth.net
Fri Nov 19 13:13:42 CET 2004


Ville Vainio wrote:

>Anyone know any good, low-fat, Open Source (BSD or better) trivial
>plugin framework that would allow me to put a bunch of .py-files in a
>directory, with contents like:
>
># /tmp/py/mymod.py
>
>class C:
>  pass
>
>class CFact:
>  pass
>
>__plugindict__ = {
>  'somefactory' : CFact
>}
>
>
>And then do
>
>import plugin
>
># sees that implementation repository doesn't exist, so creates one by
># looking at all the modules. Having seen that 'somefactory' is in
># mymod.py it only execs that.
>
>fact = plugin.get("/tmp/py", 'somefactory')
>
>obj = fact()
>
>?
>
>It seems easy enough to do, in fact I'm implementing one as I speak
>(well, not physically possible but anyway ;-), but I figured there has
>to be something that fits the bell better than my would-be
>implementation.
>
>  
>
It's been a while since I messed with it, but Retic 
(http://retic.sourceforge.net/ - a Jython EAI Server) has something like 
that.  Retic has the need for several different types of plugins (pipes, 
sources, sinks, etc), so it has several plugin directories.  You may not 
need this.  Here's the source for objectFactory.py (in the Retic project):


import sys, os

sys.path.append('pipes')
sys.path.append('sources')
sys.path.append('sinks')
sys.path.append('preprocessors')
sys.path.append('postprocessors')

srcList = os.listdir('sources')
pipeList = os.listdir('pipes')
sinkList = os.listdir('sinks')
preprocList = os.listdir('preprocessors')
postprocList = os.listdir('postprocessors')

sources = []
pipes = []
sinks = []
preprocessors = []
postprocessors = []
srcDict = {}
pipeDict = {}
sinkDict = {}
preprocessorDict = {}
postprocessorDict = {}

for src in srcList:
    if src[-3:].lower() == '.py':
        srcDict[src[:-3]] = __import__(src[:-3],globals(),locals())

for pipe in pipeList:
    if pipe[-3:].lower() == '.py':
        pipeDict[pipe[:-3]] = __import__(pipe[:-3],globals(),locals())


for sink in sinkList:
    if sink[-3:].lower() == '.py':
        sinkDict[sink[:-3]] = __import__(sink[:-3],globals(),locals())

for preproc in preprocList:
    if preproc[-3:].lower() == '.py':
        preprocessorDict[preproc[:-3]] = 
__import__(preproc[:-3],globals(),locals())

for postproc in postprocList:
    if postproc[-3:].lower() == '.py':
        postprocessorDict[postproc[:-3]] = 
__import__(postproc[:-3],globals(),locals())

#import fileSource, toXMLPipe, fileSink, ftpSource, HTTPSource, ftpSink, 
XSLTPipe, SQLSource
#import SMTPSink, SQLSink, XPath, XMLToFlatPipe, SQLTreeSource, 
SQLTreeSourcePlus
#import shellSink, XindiceSink, xmlBlasterSink, xmlBlasterSource, 
JMSSource, JMSSink

class Factory:

    def createObject(self, kind, args, logger):

        #=========================================================#
        #                       SOURCES
        #=========================================================#
        if kind == 'source':
            object = srcDict[args['type']].source(args, logger)
        #=========================================================#
        #                       PIPES
        #=========================================================#
        elif kind == 'pipe':
            object = pipeDict[args['type']].pipe(args, logger)
        #=========================================================#
        #                       SINKS
        #=========================================================#
        elif kind == 'sink':
            object = sinkDict[args['type']].sink(args, logger)
        #=========================================================#
        #                       PREPROCESSORS
        #=========================================================#
        elif kind == 'preproc':
            object = preprocessorDict[args['type']].preprocessor(args, 
logger)
        #=========================================================#
        #                       POSTPROCESSORS
        #=========================================================#
        elif kind == 'postproc':
            object = postprocessorDict[args['type']].postprocessor(args, 
logger)

        return object


If there is a problem with this approach, it is that the directories of 
files are evaulated at import time of this module.  So, once you import 
it, if you drop a new file in the directory, you have to do a 
reload(objectFactory) or you have to restart your process.  But, it 
should not be a huge problem to make that dynamic - maybe cache the file 
list and whenever a createObject is called, check the plugin directories 
and see if anything has changed and if so, update the particular plugin 
type - or something like that.  But, I do remember this working really 
well and being a useable plugin approach and a really cool project IMHO, 
but YMMV.


Jeremy Jones

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20041119/b33b956b/attachment.html>


More information about the Python-list mailing list