Module: getargs
Revision: 2.14

Author: Vinod Vijayarajan <vinod.vijayarajan@hp.com>
Copyright (c) 2004-2005, Vinod Vijayarajan
   
This module implements a Command Line Parser class (CLParser) that 
applications can use to parse command line arguments in sys.argv. 
getargs is designed as a considerably more powerful and flexible alternative
to the standard getopt module.

The CLParser provides the following capabilities:
 - Each command line option can take an arbitrary number of arguments.
 - Distingushes between switches (options without arguments) and options
   with arguments.
 - Recognizes 'single-argument-options' and 'default-if-set' options.
 - Switches and options with arguments can be interleaved in the command
   line.
 - You can specify the maximum and minimum number of arguments an option
   can take. Use -1 if you don't want to specify an upper bound.
 - Specify default arguments to an option
 - Optionally, type-checks arguments to an option
 - Returns arguments to an option according to type
 - Short options can be upto 2 letters in length.
 - A given option may be invoked by multiple names.
 - Recognizes by default the --help/-h/--version options
 - Arguments need not all be on the commandline. They can be specified
   in a file too.
 - Arguments may be specified using the '=' and ',' syntax also.
 - Methods isset() and getargs() to check if a switch (an option without
   arguments) is set (present) on the commandline and to obtain arguments
   to an option, respectively

The CLParser expects as input:
 - The entire command line, including the script name (sys.argv)
 - A dictionary whose items describe each possible option in the following
   format:
   'long_opt' : ('short_opt', [type], max_args, min_args, [defaults])

   long_opt and short_opt are long and short forms of the option.
   short_opt may be max 2 characters in length. 
   (eg: -bs is allowed and considered a short option)

   If an option can be invoked by multiple names on the command line
   use the following syntax to specify this:
   'long_form1/long_form2' : ( 'short_opt', ... )

   Eg:  'nodes/machines' : ('n', int, 4, 2)
        'block-size/seg-size' : ('bs/ss', int, 1, 1, 128)
        
   The optional type field may be specified to invoke type-checking
   of arguments to this option. Though, this will work for all types
   supported by Python, by far the most useful are int and str

   *** Specifying the type has one other benefit. The code will then
   automagically convert the arguments to the specified type before
   returning them to the program. Previously, all arguments were 
   returned as strings. ***

   Note: type may be one of int, str, float etc. Notice that these
   are to be specified as such, not in quotes as strings.

   Eg:  'file' : ('f', str, -1, 1, 'default')
        'block-size' : ('bs', int, 1, 1, 128)

   max_args/min_args are what they seem to be - the most/least
   number of arguments a option can/must have.
    
   The 'defaults' field is optional and is used to specify default
   arguments to an option. These will be assigned to the option if 
   it is *not* seen on (used in) the command line.
   Default values can be -
       - a value for options that require a single argument
       - a list for options with more than one possible argument.
   Default values are mandatory for 'default-if-set' options.

   If max_args is 0 (option is just a switch), min_args is ignored.
   If max_args is -1, then option can have any number of arguments 
   greater/equal to min_args

   If max_args == min_args == 1, the option is treated as a single
   argument option.

   If max_args >= 1 and min_args == 0, the option is treated as a
   'default-if-set' option. This implies that it is only if the
   option is encountered on the command line without any arguments,
   that it is assigned the 'defaults' value. (Note: defaults must 
   be specified for such options) 
   If absent from the command line altogether, the defaults are 
   *not* applied. If an argument 'arg' is specified on the command
   line, then 'arg' is assigned to the option.
   Thus -
       a --debug in the command line would cause debug = 1
       a --debug 2 in the command line would result in debug = 2
       if unused on the command line, debug = []

   You can also ask the module to read in arguments from a file.
   The file name must be prepended with a '@', thusly -
           
       test.py @test.opt          
       test.py @test.opt -v -bs128

Usage:
  The CLParser class provides two methods to access options from the 
  parsed command line. These are:
   - isset(option)   : Used to check whether a switch 'option' is set 
                       (present) on the commandline.
                       Returns 1 if set, 0 if not.
   - getargs(option) : Used to obtain arguments to an option.
                       If 'option' is used in the commandline, returns
                       either a value (for single argument options) or the
                       list of arguments to 'option'. Even if 'option' is 
                       not used but has defaults specified, these are 
                       returned.
                       An empty list [] is returned otherwise.

Format of the opt_file:
  The user can ask the module to read in options and arguments from a
  file using the 'prog_name @opt_file' directive. The opt_file must obey 
  the following syntax:

   - All lines beginning with '#' are considered comment lines
   - You can have comments inline, following whatever is valid on the line.
   - Arguments and options can be written just as you would on the
     command line *with* the '-' and '--'s. You can intersperse them, as
     you please, across lines.
   - Arguments that contain spaces in them must be written as they would
     be on the prompt with \'s, thusly:
         --file this\ file.py that\ file.py
   - If you want arguments you specify in the opt_file to be globbed (i.e
     they contain wildcards), remember to enclose them in quotes(''/"")
     thusly:
         --file '*.py' "file.*"   # Can be 'single' or "double" quotes
  
  Important: The options/arguments specified in the opt_file are considered
  in place on the command line. As such, if you wish arguments (for an 
  option) specified on the command line to override arguments specified in 
  the opt_file, remember to position the @opt_file directive before the said
  arguments on the command line.

  Variants of the above theme:
    You may also choose not to override, but to append to arguments specified
    in the opt_file by using the '++option arg' directive on the command line,
    rather than the usual '--option arg'
    Eg:
       test.py @test.opt ++file another.py
    
    In this case, if '--file a.py b.py' was given in test.opt, 'file' would
    have as arguments, ['a.py', 'b.py', 'another.py']

    Note: The '++' notation can only be used for options that have been 
    encountered atleast once previously by the parser. An UsageError is
    thrown if this is the first instance of the option.

Example:
  Say sys.argv is 'test.py @test.opt -vb128 --file *.pyc hell.pyo -n 2 3'
    
   opt_f = { 'verbose' : ('vb', 0), 'block-size' : ('bs', 1, 1), 
             'file' : ('f', -1, 1), 'nodes/machines' : ('n/m', 4, 1), 
             'log' : ('l', 1, 1, 'a default.log'), 'debug' : ('d', 1, 0, 1)
           }
     
   try:
      clparser = CLParser(opt_f, sys.argv)
   except UsageError, err:
      print 'error:', err
      usage()
      sys.exit(1)
     
   files = clparser.getargs('f')            # returns a list
   bsize = clparser.getargs('block-size')   # returns a value
   log_file = clparser.getargs('l')         # returns 'a default.log'
   debug_lvl = clparser.getargs('debug')    # debug is default-if-set option
     
   if clparser.isset('verbose'):
      print 'I'm going to talk an awful lot'

Exceptions:
  Throws HelpQuery when a '--help' or '-h' is encountered on the command line
  Throws VersionQuery when a '--version' is seen on the command line
  Throws UsageError, KeyError or ValueError exceptions.
