On Feb 12, 4:48 pm, [EMAIL PROTECTED] wrote: > - is there a better way than using multiple inheritance to plug-in > dynamically commands in a Cmd command line?
I had to solve the same problem recently, and I decided to avoid multiple inheritance by using delegation. My idea was to make the Cmd class a wrapper around an object with 'do_' methods. I give you the code as it is, without much explanations: just run it and give "help" on the command line. You can cut the part about the 'do_input' method which I needed in order to pass lists of strings to the inner object. Hope you can find some useful trick for solving your problem. Michele Simionato import sys, cmd, traceback, inspect try: # Python 2.5 from functools import update_wrapper except ImportError: def update_wrapper(wrapper, wrapped, assigned=('__module__', '__name__', '__doc__'), updated=('__dict__',)): for attr in assigned: setattr(wrapper, attr, getattr(wrapped, attr)) for attr in updated: getattr(wrapper, attr).update(getattr(wrapped, attr)) return wrapper def makewrapper(meth): if inspect.ismethod(meth): func = meth.im_func elif inspect.isfunction(meth): func = meth else: raise TypeError('%r must be a regular function or method' % meth) return update_wrapper(lambda self, arg: meth(arg), func) # dispatch the input dictionary to self.innerobj def do_input(self, arg): if arg.split(): # passed some argument of type 'name <args>' try: name, args = arg.split(' ', 1) except ValueError: print 'Wrong format: use the format input <name> <values>' else: self.inputdict[name] = args.split(self.inputsep) else: self.innerobj.input(self.inputdict) self.inputdict = {} def copy_interface_methods(innerobj, _CLI): for attr in dir(innerobj): if attr.startswith('do_'): setattr(_CLI, attr, makewrapper(getattr(innerobj, attr))) elif attr == 'input': do_input.__doc__ = innerobj.input.__doc__ _CLI.do_input = do_input class CLI(cmd.Cmd, object): """ Wraps an object with 'do_' methods with a command line interface. """ def __new__(cls, innerobj, completekey='tab', stdin=None, stdout=None, nonblocking=False): class _CLI(cls): prompt = 'CLI> ' if stdin is not None: use_rawinput = False copy_interface_methods(innerobj, _CLI) return super(CLI, cls).__new__( _CLI, innerobj, completekey, stdin, stdout) def __init__(self, innerobj, completekey='tab', stdin=None, stdout=None): self.innerobj = innerobj if hasattr(self, 'do_input'): self.inputdict = {} self.inputsep = '|' cmd.Cmd.__init__(self, completekey, stdin, stdout) def onecmd(self, line): # enable comments if not line.startswith('#'): return super(CLI, self).onecmd(line) def emptyline(self): # does not repeat the last command pass def do_EOF(self, arg): "Called when you enter CTRL-D, it stops the command loop" return 1 if __name__ == '__main__': # test class PrintableObj(object): def __init__(self, x, y): self.x = x self.y = y def do_print(self, arg): "example" print self.x, self.y def input(self, dict_of_lists): 'just print the entered value' vars(self).update(dict_of_lists) print dict_of_lists cli = CLI(PrintableObj([], [])) cli.cmdloop() -- http://mail.python.org/mailman/listinfo/python-list