From: kaklis on
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
From: Tim Chase on
On 05/17/2010 07:11 AM, kaklis(a)gmail.com wrote:
> 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

You simply receive all the text after the command:

class C(Cmd):
def do_thing(self, arguments):
print repr(arguments)

If you want to split it, you can do it boringly:

def do_thing(self, arguments):
args = arguments.split()

or you can let Python's standard library do some heavy-lifting
for you:

import shlex
#...
def do_thing(self, arguments):
args = shlex.split(arguments)

-tkc



From: kaklis on
On May 17, 4:12 pm, Tim Chase <python.l...(a)tim.thechases.com> wrote:
> On 05/17/2010 07:11 AM, kak...(a)gmail.com wrote:
>
> > 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
>
> You simply receive all the text after the command:
>
>    class C(Cmd):
>      def do_thing(self, arguments):
>        print repr(arguments)
>
> If you want to split it, you can do it boringly:
>
>      def do_thing(self, arguments):
>        args = arguments.split()
>
> or you can let Python's standard library do some heavy-lifting
> for you:
>
>    import shlex
>    #...
>      def do_thing(self, arguments):
>        args = shlex.split(arguments)
>
> -tkc

Thanks, great answer!!!
From: Peter Otten on
kaklis(a)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
From: kaklis on
On May 17, 4:34 pm, Peter Otten <__pete...(a)web.de> wrote:
> kak...(a)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

Thanks great advice!
Antonis