ANNOUNCE: Optik 1.0 (new command-line parsing library)

Greg Ward gward at python.net
Mon Nov 12 10:26:12 EST 2001


On 12 November 2001, Oleg Broytmann said:
>    Can it handle multiple arguments for an option?
> 
> <yourscript> --file outfile1 outfile2

No, but Optik supports callback options so you can easily do it
yourself.  Something like this:

  def process_many (option, opt, value, parser, nargs):
      if len(parser.args) < nargs:
          raise OptionValueError(
              "%s option requires %d arguments" % (opt, nargs))
      setattr(parser.values, option.dest, parser.args[0:nargs])
      del parser.args[0:nargs]

  [...]
  parser = OptionParser(...)
  parser.add_option("--file",
                    action="callback", dest="filenames",
                    callback=process_many, callback_args=(2,))

Completely off the top of my head, untested, YMMV, RTFM for more info,
etc. etc.

Alternately, you could add a new action, eg. "store_many", to the Option
class.  (Well, to your own Option subclass.)  That would be more
general, and might make it easier to put Optik's type system to use --
eg. you could have one "store_many" option that expects two strings, and
another that expects 3 floats.  If you add a "file" type (where
type-checking means "check that this file exists"), you could make one
that expects two files.  See extending.txt, or just bug me again and
maybe I'll do it.

>    Or mix options and arguments?
> 
> <yourscript> --file outfile infile -q

Not yet; I deliberately punted on this because most other Unix
command-line parsing libraries are lazy and don't bother to scan all
arguments for options.  (I think scanning all arguments is the preferred
behaviour, but for historical reasons it should probably be optional
behaviour.  I could be wrong...)

However, the main loop in OptionParser.parse_args() is pretty simple:

    (args, tail_args) = self._split_args(args)
    [...]
    while args:
        arg = args[0]
        try:
            if arg[0:2] == "--":
                self._process_long_opt(args, values)
            elif arg[0] == "-":
                self._process_short_opts(args, values)
            else:
                # To add the ability to intersperse options with
                # positional arguments, change this.
                break
        except (BadOptionError, OptionValueError), err:
            self.error(err.msg)

(_split_args() just looks for "-" and "--" args, to force a halt to
option-parsing.)  

>    Handle multiple args with the same name?
> 
> <yourscript> --file outfile1 -f outfile2

Yes, but just what happens in this case depends on the action you use.
I'm assuming --file and -f are synonomous, ie.

  parser.add_option("-f", "--file", ...)

is how you defined them.  If you did

  parser.add_option("-f", "--file",
                    action="store", type="string", dest="file")

then the most recent option seen takes effect, and
  options.file == "outfile2"

But if you did

  parser.add_option("-f", "--file",
                    action="append", type="string", dest="file")

(note the different action), then all occurences of -f or --file build
up, and
  options.file == ["outfile1", "outfile2"]

In other words, you're free to define the Right Thing for your
application, and Optik will Do The Right Thing.  That's why I used
"flexible" in the description.

        Greg
-- 
Greg Ward - programmer-at-large                         gward at python.net
http://starship.python.net/~gward/
Things are never as bad as they seem -- they're worse.




More information about the Python-list mailing list