mirror of
https://github.com/python/cpython.git
synced 2025-12-09 02:35:14 +00:00
(a) "except E, V" -> "except E as V" (b) V is now limited to a simple name (local variable) (c) V is now deleted at the end of the except block
144 lines
4.5 KiB
Python
Executable file
144 lines
4.5 KiB
Python
Executable file
"Framework for command line interfaces like CVS. See class CmdFrameWork."
|
|
|
|
|
|
class CommandFrameWork:
|
|
|
|
"""Framework class for command line interfaces like CVS.
|
|
|
|
The general command line structure is
|
|
|
|
command [flags] subcommand [subflags] [argument] ...
|
|
|
|
There's a class variable GlobalFlags which specifies the
|
|
global flags options. Subcommands are defined by defining
|
|
methods named do_<subcommand>. Flags for the subcommand are
|
|
defined by defining class or instance variables named
|
|
flags_<subcommand>. If there's no command, method default()
|
|
is called. The __doc__ strings for the do_ methods are used
|
|
for the usage message, printed after the general usage message
|
|
which is the class variable UsageMessage. The class variable
|
|
PostUsageMessage is printed after all the do_ methods' __doc__
|
|
strings. The method's return value can be a suggested exit
|
|
status. [XXX Need to rewrite this to clarify it.]
|
|
|
|
Common usage is to derive a class, instantiate it, and then call its
|
|
run() method; by default this takes its arguments from sys.argv[1:].
|
|
"""
|
|
|
|
UsageMessage = \
|
|
"usage: (name)s [flags] subcommand [subflags] [argument] ..."
|
|
|
|
PostUsageMessage = None
|
|
|
|
GlobalFlags = ''
|
|
|
|
def __init__(self):
|
|
"""Constructor, present for completeness."""
|
|
pass
|
|
|
|
def run(self, args = None):
|
|
"""Process flags, subcommand and options, then run it."""
|
|
import getopt, sys
|
|
if args is None: args = sys.argv[1:]
|
|
try:
|
|
opts, args = getopt.getopt(args, self.GlobalFlags)
|
|
except getopt.error as msg:
|
|
return self.usage(msg)
|
|
self.options(opts)
|
|
if not args:
|
|
self.ready()
|
|
return self.default()
|
|
else:
|
|
cmd = args[0]
|
|
mname = 'do_' + cmd
|
|
fname = 'flags_' + cmd
|
|
try:
|
|
method = getattr(self, mname)
|
|
except AttributeError:
|
|
return self.usage("command %r unknown" % (cmd,))
|
|
try:
|
|
flags = getattr(self, fname)
|
|
except AttributeError:
|
|
flags = ''
|
|
try:
|
|
opts, args = getopt.getopt(args[1:], flags)
|
|
except getopt.error as msg:
|
|
return self.usage(
|
|
"subcommand %s: " % cmd + str(msg))
|
|
self.ready()
|
|
return method(opts, args)
|
|
|
|
def options(self, opts):
|
|
"""Process the options retrieved by getopt.
|
|
Override this if you have any options."""
|
|
if opts:
|
|
print "-"*40
|
|
print "Options:"
|
|
for o, a in opts:
|
|
print 'option', o, 'value', repr(a)
|
|
print "-"*40
|
|
|
|
def ready(self):
|
|
"""Called just before calling the subcommand."""
|
|
pass
|
|
|
|
def usage(self, msg = None):
|
|
"""Print usage message. Return suitable exit code (2)."""
|
|
if msg: print msg
|
|
print self.UsageMessage % {'name': self.__class__.__name__}
|
|
docstrings = {}
|
|
c = self.__class__
|
|
while 1:
|
|
for name in dir(c):
|
|
if name[:3] == 'do_':
|
|
if docstrings.has_key(name):
|
|
continue
|
|
try:
|
|
doc = getattr(c, name).__doc__
|
|
except:
|
|
doc = None
|
|
if doc:
|
|
docstrings[name] = doc
|
|
if not c.__bases__:
|
|
break
|
|
c = c.__bases__[0]
|
|
if docstrings:
|
|
print "where subcommand can be:"
|
|
names = docstrings.keys()
|
|
names.sort()
|
|
for name in names:
|
|
print docstrings[name]
|
|
if self.PostUsageMessage:
|
|
print self.PostUsageMessage
|
|
return 2
|
|
|
|
def default(self):
|
|
"""Default method, called when no subcommand is given.
|
|
You should always override this."""
|
|
print "Nobody expects the Spanish Inquisition!"
|
|
|
|
|
|
def test():
|
|
"""Test script -- called when this module is run as a script."""
|
|
import sys
|
|
class Hello(CommandFrameWork):
|
|
def do_hello(self, opts, args):
|
|
"hello -- print 'hello world', needs no arguments"
|
|
print "Hello, world"
|
|
x = Hello()
|
|
tests = [
|
|
[],
|
|
['hello'],
|
|
['spam'],
|
|
['-x'],
|
|
['hello', '-x'],
|
|
None,
|
|
]
|
|
for t in tests:
|
|
print '-'*10, t, '-'*10
|
|
sts = x.run(t)
|
|
print "Exit status:", repr(sts)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
test()
|