Re: Re: [PATCH] %default keyword expansion

John Belmonte <[email protected]> Mon, 17 May 2004 00:12:13 -0400
Newsgroups gmane.comp.python.optik.user
Message-ID <[email protected]>
Greg Ward wrote:
> New patch attached.  This includes a fairly robust set of tests, which
> is probably the best documentation of the new feature for now.  Please
> give it a spin and let me know if it works for you.  I like it; I think
> I'll probably check this in some time this week.

It works fine, yet my trouble making continues...

Just last week I used custom option types for the first time, and was 
thinking "I guess that %default expansion thing I proposed needs to be 
tossed out the window".  (See attached example.)

Actually, %default expansion is innocent here.  The problem is that 
defaults are not run through the option's checker/converter.  For types 
which are converted, why shouldn't the programmer be able to give the 
same value for a default that the user would put on the command line, 
rather than have to mentally convert to a normalized value?  I've run 
into the same issue with ZConfig, and it seems like a design error to 
me.  The %default expansion just makes the issue more obvious.

I propose that Option and add_option take a new keyword "nice_default". 
  Nice defaults are passed through the option checker just as if they 
were passed on the command line.  In this case, %default will expand to 
the pre-checked value.

Regards,
-John


-- 
http:// ift ile.org/
test-opt.py (text/x-python, 1.2 KB)
from copy import copy
from optparse import OptionParser, Option

_time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }

def _get_duration(value):
    if not value[-1].isdigit():
        return int(value[:-1]) * _time_units[value[-1]]
    else:
        return int(value)

def _check_duration(option, opt, value):
    try:
        return _get_duration(value)
    except ValueError, IndexError:
        raise OptionValueError(
            'option %s: invalid duration: %r' % (opt, value))

class MyOption(Option):
    TYPES = Option.TYPES + ('duration',)
    TYPE_CHECKER = copy(Option.TYPE_CHECKER)
    TYPE_CHECKER['duration'] = _check_duration

class MyOptionParser(OptionParser):
    def __init__(self):
        OptionParser.__init__(self, option_class=MyOption,
            usage='usage: %prog [options]')
        self.add_option(
            '--delay',
            type='duration',
            # oops, default doesn't run through type checker
            #default='5m',
            default=60,
            help='self destruct delay [default: %default]')

parser = MyOptionParser()
options, args = parser.parse_args()

print 'self destruct in %s seconds' % options.delay