multiple inheritance of a dynamic list of classes?

Peter Otten __peter__ at web.de
Mon Feb 12 11:56:15 EST 2007


devicerandom at gmail.com wrote:

> 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?

>>> import cmd
>>> class Foo:
...     def do_this(self, arg):
...             print "THIS", arg
...
>>> class Bar:
...     def do_that(self, arg):
...             print "THAT", arg
...
>>> plugins = [Foo, Bar]
>>> def make_command_class(*bases):
...     return type(cmd.Cmd)("MyCli", bases + (cmd.Cmd,), {})
...
>>> cmd = make_command_class(*plugins)()
>>> cmd.cmdloop()
(Cmd) help

Undocumented commands:
======================
help  that  this

(Cmd) that one
THAT one
(Cmd)

Most of the above should be straight-forward. I used type(cmd.Cmd)(name,
bases, classdict) instead of just type(name, bases, classdict) because
cmd.Cmd is a classic class.

The thread "Partial 1.0 - Partial classes for Python" might also be of
interest.

Peter




More information about the Python-list mailing list