Re: Default argument for an option?

Greg Ward <[email protected]> Sun, 26 Sep 2004 18:26:57 -0400
Newsgroups gmane.comp.python.optik.user
Message-ID <[email protected]>
On 26 September 2004, Thorsten Kampe said:
> I have this code:
> 
> add_option('-g',
>            '--guistyle',
>             action  = 'store',
>             dest    = 'guistyle',
>             metavar = 'STYLE',
>             nargs   = 1,
>             type    = 'string',
>             help    = 'graphical output (STYLE = none|gnome|kde|windows)')
> 
> I would like this option argument default to 'none' (which means use
> Tcl/Tk EasyGui) so it would be possible to use it like
> foobar --guistyle none
> and
> foobar --guistyle

Please read the docs before asking questions; this is covered in "The
Tao of Option Parsing".  From
http://optik.sourceforge.net/doc/stable/tao.html:

"""
Some options never take an argument. Some options always take an
argument. Lots of people want an "optional option arguments" feature,
meaning that some options will take an argument if they see it, and
won't if they don't. This is somewhat controversial, because it makes
parsing ambiguous: if "-a" takes an optional argument and "-b" is
another option entirely, how do we interpret "-ab"? Because of this
ambiguity, Optik does not support this feature.
"""

I should note that I am one of the people who wants optional option
arguments, but I can only think of one case offhand where I've really
wanted them badly.  (The distutils "install" command has a --home option
that *should* mean "install to my home directory, or if I supply a
directory to --home, use it instead of my home directory.  Instead, you
must supply a directory to --home, which is mildly annoying.)

Anyways, a couple of years ago I took two cracks at implementing
optional option arguments for Optik; I'll attach the first attempt,
which was not a complete failure.  (I never finished the second attempt,
so I guess it's a failure.)  The right thing to do here is *not*
obvious!

        Greg
-- 
Greg Ward <[email protected]>                         http://www.gerg.ca/
Dyslexics of the world, untie!
optional_arg_1.py (text/x-python, 1.9 KB)
#!/usr/bin/env python

# "Optional option arguments" with Optik, version 1:
# supply a callback function to handle options with
# optional arguments.
#
# There are lots of problems with this approach:
#   * doesn't allow "--home=~"; only "--home" and "--home ~" work
#   * doesn't allow "-afoo"; only "-a" or "-a foo" work
#   * option type can't be specified, because that makes
#     OptionParser require a value
#   * all the logic about what "-" and "--" mean is duplicated
#     in the callback here
#   * it's awkward as hell to use
# 
# This just shows that Optik's current design is ill-suited
# to handling optional option args.  Hmm.

from optik import OptionParser, Option

def optional_arg(option, opt, value, parser, option_default=None):

    assert value is None
    value = option_default

    # If there is a next argument, peek at it to see if it can
    # be considered an argument to 'opt'.
    if parser.rargs:
        arg = parser.rargs[0]

        if arg[0:2] == "--" or arg[0:1] == "-":
            # Either arg is another option -- "--foobar", "-a" -- or
            # it's one of the special stop-values, "--" or "-".
            # In either case, we consider it special and do *not*
            # consume it as an argument to the current option.
            pass
        else:
            # Otherwise, consume arg and use it as the value for 'option'.
            value = arg
            del parser.rargs[0]

    setattr(parser.values, option.dest, value)


parser = OptionParser()
parser.add_option("-v", action="callback", dest='verbose',
                  callback=optional_arg,
                  callback_kwargs={'option_default': 1})
parser.add_option("-l", "--log-file", action="callback", dest='log_file',
                  callback=optional_arg,
                  callback_kwargs={'option_default': "foo.log"})
(options, args) = parser.parse_args()

print "options.verbose = %r" % options.verbose
print "options.log_file = %r" % options.log_file