[TransWarp] Extending AbstractCommand
John Landahl
john at landahl.org
Tue Oct 14 17:30:47 EDT 2003
And now for something completely different. I'm looking to add a subclass
of AbstractCommand which does automatic option parsing using
Optik/OptionParser. Below is what I've done so far, which seems to work
pretty well. Any suggestions or comments?
def parser():
try: return importString('OptionParser.OptionParser')
except:
try: return importString('optik.OptionParser')
except: return None
parser = parser()
class OptionedCommand(AbstractCommand):
optionList = binding.Require('List of option descriptors')
def parser(self):
if parser: return parser()
else: return None
parser = binding.Make(parser)
def parsedOptions(self):
if not self.parser:
return (None, None)
for opt in self.optionList:
if type(opt) in [types.ListType, types.TupleType]:
opt = dict(opt)
elif type(opt) is not types.DictType:
continue
args = opt['options']
del opt['options']
self.parser.add_option(*args, **opt)
return self.parser.parse_args(self.argv[1:])
parsedOptions = binding.Make(parsedOptions)
options = binding.Make(lambda self: self.parsedOptions[0])
args = binding.Make(lambda self: self.parsedOptions[1])
An example command class:
class aCommand(OptionedCommand):
usage = '''Usage: aCommand -c <arg> -d <arg>'''
optionList = binding.Make(lambda:
[
Items(options=('-c', '--create'), action='store',
type='string', dest='create'),
Items(options=('-d', '--delete'), action='store',
type='string', dest='delete'),
]
)
def _run(self):
print 'create:', self.options.create
print 'delete:', self.options.delete
print 'args: ', self.args
Using the example manually:
r = config.makeRoot()
c = aCommand(r, argv=['aCommand', '-c', 'cArg'])
It seems that this could be extended to use Optik's built-in help
generator to build the usage string dynamically.
I really like how PEAK's binding and "create once" functionality allows
the results of arbitrarily complex code to be provided as properties.
This is an amazing leap forward in code reusability and flexibility, and
makes for classes that are very easy to use and extend. In this example,
writers of OptionedCommand subclasses need only provide a list of option
descriptors, and may then simply use self.options and self.args as needed
-- without needing to know that they spring into life on demand and are
the result of several dynamic layers of computation. This is really great
stuff.
More information about the PEAK
mailing list