trouble with cmd.Cmd and prompting

Cameron Simpson cs at zip.com.au
Mon Jan 2 19:33:15 EST 2017


I'm using cmd.Cmd to write a little FTP-like command line to interface to a 
storage system of mine and encountering weird behaviour. When I enter a command 
the next prompt appears _before_ the associated operation runs, or so it 
appears.
Look at this:
 [~/hg/css-venti(hg:venti)]fleet*> dev ./bin/vt -M -C - -S '[archive]' ftp ~/var/mnt/archive.vt
 stores = [<cs.venti.store.DataDirStore object at 0x10a564a90>]
 S = Store(MappingStore(ConfigWatcher('/Users/cameron/.vtrc')[archive]))
 ~/var/mnt/archive.vt:/> ls
 ~/var/mnt/archive.vt:/> precmd: line='ls'
 ---------- OnyX.dmg
 postcmd: stop=None, line='ls'
See how the cmd.Cmd prompt "~/var/mnt/archive.vt:/> " appears again right after 
the "ls", and before its output:
 precmd: line='ls'
 ---------- OnyX.dmg
 postcmd: stop=None, line='ls'
The precmd and postcmd lines are debugging, emitted from my precmd and postcmd 
methods in the subclass.
Has anyone seen this kind of thing before?
The salient parts of my class are shown below. It's not complete and I'm happy 
to post the full thing if people need to see it. The behaviour is the same 
regardless of the command; even an empty command shows it:
 ~/var/mnt/archive.vt:/> precmd: line=''
 postcmd: stop=None, line=''
 ~/var/mnt/archive.vt:/> precmd: line=''
 postcmd: stop=None, line=''
Any insights or suggestions welcome. Code below.
Cheers,
Cameron Simpson <cs at zip.com.au>
from cmd import Cmd
import readline
class FTP(Cmd):
 def __init__(self, D, sep=None, FS=None, prompt=None):
 Cmd.__init__(self)
 self._prompt = prompt
 if sep is None:
 sep = '/' # NB: _not_ os.sep
 self.root = D
 self.cwd = D
 self.sep = sep
 self.fs = FS
 self._set_prompt()
 def _set_prompt(self):
 prompt = self._prompt
 pwd = '/' + self.op_pwd()
 self.prompt = ( pwd if prompt is None else ":".join( (prompt, pwd) ) ) + '> '
 def precmd(self, line):
 X("precmd: line=%r", line)
 return line
 def postcmd(self, stop, line):
 X("postcmd: stop=%s, line=%r", stop, line)
 self._set_prompt()
 return stop
 def emptyline(self):
 pass
 def do_EOF(self, args):
 ''' Quit on end of input.
 '''
 return True
 def do_quit(self, args):
 ''' Usage: quit
 '''
 return True
 def do_ls(self, args):
 ''' Usage: ls [paths...]
 '''
 argv = shlex.split(args)
 if not argv:
 argv = sorted(self.cwd.entries.keys())
 for name in argv:
 with Pfx(name):
 E, P, tail = resolve(self.cwd, name)
 if tail:
 error("not found: unresolved path elements: %r", tail)
 else:
 M = E.meta
 S = M.stat()
 u, g, perms = M.unix_perms
 typemode = M.unix_typemode
 typechar = ( '-' if typemode == stat.S_IFREG
 else 'd' if typemode == stat.S_IFDIR
 else 's' if typemode == stat.S_IFLNK
 else '?'
 )
 print("%s%s%s%s %s" % ( typechar,
 rwx((typemode>>6)&7),
 rwx((typemode>>3)&7),
 rwx((typemode)&7),
 name
 ))


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /