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