cmd with three arguments

Peter Otten __peter__ at web.de
Mon May 17 09:34:10 EDT 2010


kaklis at gmail.com wrote:

> Hi pythonistas,
> While playing with the Python Standard Library, i came across "cmd".
> So I'm trying to make a console application. Everything works fine, i
> created many function with do_....(self, line) prefix, but when i
> tried to create a function with more arguments
>  i can't make it work.  e.g
> def do_connect(self, ip, command):
> 
>>>> connect 127.0.0.1 delete
>  Are there any work arounds
> 
> Thanks in advance
> 
> Antonis

You have to split the user input into arguments yourself. You can do this in 
the body of the do_xxx() methods, use a decorator, or subclass cmd.Cmd.

Here's a solution using a decorator:

import cmd
import inspect
import shlex

def split(f):
    def g(self, line):
        argvalues = shlex.split(line)
        argnames = inspect.getargspec(f).args
        argcount = len(argnames) - 1
        if len(argvalues) != argcount:
            print "Need exactly %d args" % argcount
            return
        return f(self, *argvalues)
    return g

class Cmd(cmd.Cmd):
    @split
    def do_connect(self, ip, command):
        print "ip=%r, command=%r" % (ip, command)


if __name__ == "__main__":
    c = Cmd()
    c.cmdloop()

And here's a subclass that avoids the need for explicit @split decorations:

import cmd
import inspect
import shlex

def split(f):
    def g(line):
        argvalues = shlex.split(line)
        argnames = inspect.getargspec(f).args
        argcount = len(argnames) -1
        if len(argvalues) != argcount:
            print "Need exactly %d args" % argcount
            return
        return f(*argvalues)
    return g

class CmdBase(cmd.Cmd, object):
    def __getattribute__(self, name):
        attr = object.__getattribute__(self, name)
        if name.startswith("do_"):
            attr = split(attr)
        return attr

class Cmd(CmdBase):
    def do_connect(self, ip, command):
        print "ip=%r, command=%r" % (ip, command)


if __name__ == "__main__":
    c = Cmd()
    c.cmdloop()

Now you've got an idea of the general direction you can certainly come up 
with something less hackish ;)

Peter



More information about the Python-list mailing list