multiple callbacks
[email protected] Thu, 26 Jun 2008 19:17:44 -0500
| Newsgroups | gmane.comp.python.optik.user |
|---|---|
| Message-ID | <OF500744C6.956AAD48-ON86257474.008259C5-86257475.00019F8F@uscmail.uscourts.gov> |
Hi. So I had come up with my own way of parsing through options and
determining what was good and what needed to be errored. No big deal. Had
a thought that it would be kewl to extend Options to handle this
automagically, and then it occurred to me that I should probably re-check
the documentation. Apparently I stopped reading it before I got to the
good bits (ain't that always the case?).
So after reading through the docs and looking in the code a bit (gotta love
open source), it occurred to me that it might be a "nice" feature to be
able to provide multiple callbacks per option.
Here is a use case:
I have 3 options that I want the user to provide. 2 directories and 1
file. I want to verify that the directories both exist, and are actually
directories. I want 1 directory to be an absolute path and also writeable.
I want to also verify that the file exists and is writeable. I've written
4 callbacks that could handle that, without repeating code, but only if I
could pass multiple functions through callback.
ie:
#!/usr/bin/env python
from optparse import make_options, OptionParser, OptionValueError
import os
OPTIONS_LIST = [
make_option('-c', '--chroot', default=None,
action='callback', callback=(check_path_exists, check_path_isdir),
help="specifies the root of the chroot environment to work with"),
make_option('-w', '--working', default=None,
action='callback', callback=(check_path_exists, check_path_isdir,
check_writeable),
help="specifies the working directory"),
make_option('-o', '--output', default=None,
action='callback', callback=(check_path_exists, check_writeable),
help="specifies the file to save the output to"),
make_option('-d', '--debug', action="store_true", default=False,
help="enable debugging")
]
def check_path_exists(option, opt_str, value, parser):
if (not os.path.exists(value)):
raise OptionValueError('Specified %s path does not exist' %
(opt_str))
setattr(parser.values, option.dest, value)
def check_path_isdir(option, opt_str, value, parser):
if (not os.path.isdir(value)):
raise OptionValueError('Specified %s path is not a directory' %
(opt_str))
setattr(parser.values, option.dest, value)
def check_abspath(option, opt_str, value, parser):
if (not options.working.startswith("/")):
raise OptionValueError("Specified directory must reference an absolute
path")
setattr(parser.values, option.dest, value)
def check_writable(option, opt_str, value, parser):
if (not os.access(options.output, os.W_OK)):
raise OptionValueError('Cannot write to location provided')
setattr(parser.values, option.dest, value)
p = OptionParser(OPTION_LIST)
(options, args) = p.parse_args()
######### End script
This of course doesn't work at this point.... but a simple modification to
2 spots inside the {optik,optparse}.py such as this:
Make this change in Option._check_callback (approx line704)
Before:
def _check_callback(self):
if self.action == "callback":
if not callable(self.callback):
raise OptionError(
"callback not callable: %r" % self.callback, self)
After:
def _check_callback(self):
if self.action == "callback":
if type(self.callback) is not types.TupleType:
self.callback = (self.callback,)
for cb in self.callback:
if not callable(cb):
raise OptionError(
"callback not callable: %r" % cb, self)
Then in Option.take_action (approx line 804):
Before:
elif action == "callback":
args = self.callback_args or ()
kwargs = self.callback_kwargs or {}
self.callback(self, opt, value, parser, *args, **kwargs)
After:
elif action == "callback":
args = self.callback_args or ()
kwargs = self.callback_kwargs or {}
for cb in self.callback:
cb(self, opt, value, parser, *args, **kwargs)
Anyways... just a thought. There is probably more to the change (and I'm
sure a unittest would have to probably be made/adjusted) but I just wanted
to throw it out there.
-greg
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php