| "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, 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 %s unknown" % `cmd`) | 
 | 			try: | 
 | 				flags = getattr(self, fname) | 
 | 			except AttributeError: | 
 | 				flags = '' | 
 | 			try: | 
 | 				opts, args = getopt.getopt(args[1:], flags) | 
 | 			except getopt.error, 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', `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:", `sts` | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 | 	test() |