<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Ville Vainio wrote:
<blockquote cite="middu7pt2ace26.fsf@mozart.cc.tut.fi" type="cite">
  <pre wrap="">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.

  </pre>
</blockquote>
It's been a while since I messed with it, but Retic
(<a class="moz-txt-link-freetext" href="http://retic.sourceforge.net/">http://retic.sourceforge.net/</a> - 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):<br>
<br>
<br>
<font face="Courier New, Courier, monospace">import sys, os<br>
<br>
sys.path.append('pipes')<br>
sys.path.append('sources')<br>
sys.path.append('sinks')<br>
sys.path.append('preprocessors')<br>
sys.path.append('postprocessors')<br>
<br>
srcList = os.listdir('sources')<br>
pipeList = os.listdir('pipes')<br>
sinkList = os.listdir('sinks')<br>
preprocList = os.listdir('preprocessors')<br>
postprocList = os.listdir('postprocessors')<br>
<br>
sources = []<br>
pipes = []<br>
sinks = []<br>
preprocessors = []<br>
postprocessors = []<br>
srcDict = {}<br>
pipeDict = {}<br>
sinkDict = {}<br>
preprocessorDict = {}<br>
postprocessorDict = {}<br>
<br>
for src in srcList:<br>
    if src[-3:].lower() == '.py':<br>
        srcDict[src[:-3]] = __import__(src[:-3],globals(),locals())<br>
<br>
for pipe in pipeList:<br>
    if pipe[-3:].lower() == '.py':<br>
        pipeDict[pipe[:-3]] = __import__(pipe[:-3],globals(),locals())<br>
<br>
<br>
for sink in sinkList:<br>
    if sink[-3:].lower() == '.py':<br>
        sinkDict[sink[:-3]] = __import__(sink[:-3],globals(),locals())<br>
<br>
for preproc in preprocList:<br>
    if preproc[-3:].lower() == '.py':<br>
        preprocessorDict[preproc[:-3]] =
__import__(preproc[:-3],globals(),locals())<br>
<br>
for postproc in postprocList:<br>
    if postproc[-3:].lower() == '.py':<br>
        postprocessorDict[postproc[:-3]] =
__import__(postproc[:-3],globals(),locals())<br>
<br>
#import fileSource, toXMLPipe, fileSink, ftpSource, HTTPSource,
ftpSink, XSLTPipe, SQLSource<br>
#import SMTPSink, SQLSink, XPath, XMLToFlatPipe, SQLTreeSource,
SQLTreeSourcePlus<br>
#import shellSink, XindiceSink, xmlBlasterSink, xmlBlasterSource,
JMSSource, JMSSink<br>
<br>
class Factory:<br>
<br>
    def createObject(self, kind, args, logger):<br>
<br>
        #=========================================================#<br>
        #                       SOURCES<br>
        #=========================================================#<br>
        if kind == 'source':<br>
            object = srcDict[args['type']].source(args, logger)<br>
        #=========================================================#<br>
        #                       PIPES<br>
        #=========================================================#<br>
        elif kind == 'pipe':<br>
            object = pipeDict[args['type']].pipe(args, logger)<br>
        #=========================================================#<br>
        #                       SINKS<br>
        #=========================================================#<br>
        elif kind == 'sink':<br>
            object = sinkDict[args['type']].sink(args, logger)<br>
        #=========================================================#<br>
        #                       PREPROCESSORS<br>
        #=========================================================#<br>
        elif kind == 'preproc':<br>
            object = preprocessorDict[args['type']].preprocessor(args,
logger)<br>
        #=========================================================#<br>
        #                       POSTPROCESSORS<br>
        #=========================================================#<br>
        elif kind == 'postproc':<br>
            object =
postprocessorDict[args['type']].postprocessor(args, logger)<br>
<br>
        return object</font><br>
<br>
<br>
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.<br>
<br>
<br>
Jeremy Jones<br>
<br>
</body>
</html>