Am Sonntag, 18. Juli 2004 20:52 schrieb Alex Hunsley:
Interesting, I hadn't thought of using a dict.
Using a dict would be better than 'if's, but would still require a
central part of the code to know about all the actions!
My way allows new classes to be presented and used without altering
existing code.
Also my method forces new actions to interface with 'central' code via
the available official interface, rather than having new actions
potentially put in the central code and hence have access to things
directly (which isn't a good OO design).
What I always do when I'm in your position to have an extendable API is to
create a Registry with which the possible actions can register, a general
parsing engine, which just does a dictionary lookup on some word (the
dictionary being maintained by the module which contains the Registry), and
then calls of into the appropriate code. All other modules can also use the
Registry.
Something like this:
====
Registry.py
pluginDict = {}
def registerPlugin(name,plugincallable):
pluginDict[name] = plugincallable
def queryPlugin(name):
return pluginDict[name]()
====
Plugins/__init__.py
pass
====
Plugins/Module1.py
import Registry
class Callable1(object):
def __init__(self):
print "Instantiating Callable1."
def test_method(self,*args,**kwargs):
print "In test_method."
print args, kwargs
Registry.register("callable1",Callable1)
====
Plugins/Module2.py
import Registry
class Callable2(object):
def __init__(self):
print "Instantiating Callable2."
Registry.register("callable2",Callable2)
====
Plugins.py
import os
for fname in os.listdir("Plugins"):
try:
__import__("Plugins.%s" % fname[-3],globals(),locals(),[])
except:
print "Warning: Couldn't import plugin:", fname
====
Main.py
import Registry
import Plugins
mod1 = Registry.queryPlugin("callable1")
print mod1
mod2 = Registry.queryPlugin("callable2")
print mod2
====
ParseCommand.py
import Registry
command = "callable1.test_method test 123 how are you?"
cmd = command.split(" ")
mod, attr = cmd[0].split(".",1)
mod = Registry.queryPlugin(mod)
getattr(mod,attr)(*cmd[1:])
This code only requires you to put all plugin modules into the subdirectory
Plugins of the main program directory, and could easily be extended by
rewriting Plugins.py to accomodate on demand loading/reloading of plugins,
etc. ParseCommand.py can also easily be made more "intelligent" concerning
the parsing of the actual command-line.
Is this extensible enough?
HTH!
Heiko.