multiple inheritance of a dynamic list of classes?
Kent Johnson
kent at kentsjohnson.com
Mon Feb 12 13:58:57 EST 2007
devicerandom at gmail.com wrote:
> Hi,
>
> I am currently using the Cmd module for a mixed cli+gui application. I
> am starting to refactor my code and it would be highly desirable if
> many commands could be built as simple plugins.
>
> My idea was:
> - Load a list of plugin names (i.e. from the config file, or from the
> plugins directory)
> - Import all plugins found dynamically:
> and this is easy, since I can do, for example:
>
> PLUGIN_NAMES=['foo', 'bar']
> PLUGIN_MODULES = map(__import__, PLUGIN_NAMES)
> PLUGINS = [item.Commands for item in PLUGIN_MODULES]
>
> Now, what I have to do is to define my command line class. This is
> usually done by subclassing cmd.Cmd:
>
> class MyCli(cmd.Cmd):
> ....
>
> Now I want to add the commands defined in foo.Commands and
> bar.Commands. foo.Commands contains the functions corresponding to the
> new commands this way:
> #foo.py
> class Commands
>
> def do_this(self,args):
> ...
> def do_that(self,args):
> ...
>
> I've seen I can do it by explicitely import them and using multiple
> inheritance:
>
> class MyCli(cmd.Cmd , foo.Commands, bar.Commands)
> ....
>
> so that do_this and do_that are now methods of a Cmd command line.
>
> Now:
> - how can I instead have MyCli inherit from a dynamic list of modules?
> - is there a better way than using multiple inheritance to plug-in
> dynamically commands in a Cmd command line?
Your plugins could define plain functions with names starting with do_.
Then you can create an empty subclass of cmd.Cmd and just plug in the
imported commands:
In [1]: import cmd
In [3]: def do_this(self, arg): print 'This', arg
...:
In [4]: def do_that(self, arg): print 'That', arg
...:
In [8]: class MyCmd(cmd.Cmd): pass
...:
In [9]: MyCmd.do_this = do_this
In [10]: MyCmd.do_that = do_that
In [11]: c=MyCmd()
In [12]: c.cmdloop()
(Cmd) help
Undocumented commands:
======================
help that this
(Cmd) that
That
In your code you could use introspection to locate the plugin commands,
something like
PLUGIN_MODULES = map(__import__, PLUGIN_NAMES)
for module in PLUGIN_MODULES:
for name in dir(module):
if name.startswith('do_'):
setattr(MyCmd, name, getattr(module, name))
If the plugin module defines a list of commands then use that instead of
dir(module).
Kent
More information about the Python-list
mailing list