OPTIK - ADVANCED USAGE
======================

This is reference documentation.  If you haven't read the basic
documentation in basic.txt, do so now.


Creating and populating the parser
----------------------------------

There are several ways to populate the parser with options.  One way is
to pass a list of Options to the OptionParser constructor:

  parser = OptionParser(option_list=[
      make_option("-f", "--filename",
                  action="store", type="string", dest="filename"),
      make_option("-q", "--quiet",
                  action="store_false", dest="verbose")])

(As of Optik 1.3, make_option() is an alias for the Option class,
ie. this just calls the Option constructor.  A future version of Optik
will probably split Option into several classes, and make_option() will
become a factory function that picks the right class to instantiate.)

For long option lists, it's often more convenient/readable to create the
list separately:

  option_list = [make_option("-f", "--filename",
                             action="store", type="string", dest="filename"),
                 # ... 17 other options ...
                 make_option("-q", "--quiet",
                             action="store_false", dest="verbose")]
  parser = OptionParser(option_list=option_list)

Or, you can use the 'add_option()' method of OptionParser to add options
one-at-a-time:

  parser = OptionParser()
  parser.add_option("-f", "--filename",
                    action="store", type="string", dest="filename")
  parser.add_option("-q", "--quiet",
                    action="store_false", dest="verbose")

This method makes it easier to track down exceptions raised by the
Option constructor, which are common because of the complicated
interdependencies among the various keyword arguments -- if you get it
wrong, Optik raises OptionError.

add_option() can be called in one of two ways:
  * pass it an Option instance  (as returned by make_option())
  * pass it any combination of positional and keyword arguments that are
    acceptable to make_option() (ie., to the Option constructor),
    and it will create the Option instance for you (shown above)


Defining options
----------------

Each Option instance represents a set of synonymous command-line
options, ie. options that have the same meaning and effect, but
different spellings.  You can specify any number of short or long option
strings, but you must specify at least one option string.

To define an option with only a short option string:
  make_option("-f", ...)

And to define an option with only a long option string:
  make_option("--foo", ...)

The "..." represents a set of keyword arguments that define attributes
of the Option object.  Just which keyword args you must supply for a
given Option is fairly complicated (see the various '_check_*()' methods
in the Option class if you don't believe me), but you always have to
supply *some*.  If you get it wrong, Optik raises an OptionError
exception explaining your mistake.

The most important attribute of an option is its action, ie. what to do
when we encounter this option on the command-line.  The possible actions
are:
  store        store this option's argument [default]
  store_const  store a constant value
  store_true   store a true value
  store_false  store a false value
  append       append this option's argument to a list
  count        increment a counter by one
  callback     call a specified function
  help         print a usage message including all options and the
               documentation for them

(If you don't supply an action, the default is "store".  For this
action, you may also supply 'type' and 'dest' keywords; see below.)

As you can see, most actions involve storing or updating a value
somewhere.  Optik always creates a particular object (an instance of the
Values class defined in optik.option_parser) specifically for this
purpose.  Option arguments (and various other values) are stored as
attributes of this object, according to the 'dest' (destination)
argument to make_option()/add_option().

For example, when you call
  parser.parse_args()
one of the first things Optik does is create a "values" object:
  values = Values()

If one of the options in this parser is defined with
  make_option("-f", "--file", action="store", type="string", dest="filename")

and the command-line being parsed includes any of the following:
  -ffoo
  -f foo
  --file=foo
  --file foo

then Optik, on seeing the -f or --file option, will do the equivalent
of this:
  values.filename = "foo"

Clearly, the 'type' and 'dest' arguments are (usually) almost as
important as 'action'.  'action' is the only attribute that is
meaningful for *all* options, though, so it is the most important.


Option actions
--------------

The various option actions all have slightly different requirements and
effects.  Except for the "help" action, you must supply at least one
other keyword argument when creating the Option; the exact requirements
for each action are listed here.

  * store [relevant: 'type', 'dest', 'nargs']
    The option must be followed by an argument, which is
    converted to a value according to 'type' and stored in
    'dest'.  If nargs > 1, multiple arguments will be consumed
    from the command line; all will be converted according to
    'type' and stored to 'dest' as a tuple.  See the "Option
    types" section below.

    If 'type' is not supplied, it defaults to "string".

    If 'dest' is not supplied, Optik derives a destination from the
    first long option strings (eg., "--foo-bar" -> 'foo_bar').  If there
    are no long option strings, Optik derives a destination from the
    first short option string (eg., "-f" -> 'f').

    Example:
      make_option("-f")
      make_option("-p", type="float", nargs=3, dest="point")

    Given the following command line:
      -f foo.txt -p 1 -3.5 4 -fbar.txt

    Optik will set
      values.f = "bar.txt"
      values.point = (1.0, -3.5, 4.0)
    (Actually, values.filename will be set twice, but only the
    second time is visible in the end.)

  * store_const [required: 'const', 'dest']
    The 'const' value supplied to the Option constructor is
    stored in 'dest'.

    Example:
      make_option("-q", "--quiet",
             action="store_const", const=0, dest="verbose"),
      make_option("-v", "--verbose",
             action="store_const", const=1, dest="verbose"),
      make_option(None, "--noisy",
             action="store_const", const=2, dest="verbose"),

    If "--noisy" is seen, Optik will set
      values.verbose = 2

  * store_true [required: 'dest']
    A special case of "store_const" that stores a true value
    (specifically, the integer 1) to 'dest'.

  * store_false [required: 'dest']
    Like store_true, but stores a false value (the integer 0).

    Example:
      make_option(None, "--clobber", action="store_true", dest="clobber")
      make_option(None, "--no-clobber", action="store_false", dest="clobber")

  * append [relevant: 'type', 'dest', 'nargs']
    The option must be followed by an argument, which is appended to the
    list in 'dest'.  If no default value for 'dest' is supplied (ie. the
    default is None), an empty list is automatically created when Optik
    first encounters this option on the command-line.  If nargs > 1,
    multiple arguments are consumed, and a tuple of length nargs is
    appended to 'dest'.

    The defaults for 'type' and 'dest' are the same as for the "store"
    action.

    Example:
      make_option("-t", "--tracks", action="append", type="int")

    If "-t3" is seen on the command-line, Optik does the equivalent of:
      values.tracks = []
      values.tracks.append(int("3"))

    If, a little later on, "--tracks=4" is seen, it does:
      values.tracks.append(int("4"))

    See the "Error handling" section in basic.txt for information on how
    Optik deals with something like "--tracks=x".

  * count [required: 'dest']
    Increment the integer stored at 'dest'.  'dest' is set to zero
    before being incremented the first time (unless you supply a default
    value).

    Example:
      make_option("-v", action="count", dest="verbosity")

    The first time "-v" is seen on the command line, Optik does the
    equivalent of:
      values.verbosity = 0
      values.verbosity += 1

    Every subsequent occurrence of "-v" results in
      values.verbosity += 1

  * callback [required: 'callback';
              relevant: 'type', 'nargs', 'callback_args', 'callback_kwargs']
    Call the function specified by 'callback'.  The signature of
    this function should be

      func(option : Option,
           opt : string,
           value : any,
           parser : OptionParser,
           *args, **kwargs)

    Callback options are covered in detail in callback.txt.

  * help [required: none]
    Prints a complete help message for all the options in the
    current option parser.  The help message is constructed from
    the 'usage' string passed to OptionParser's constructor and
    the 'help' string passed to every option.

    If no 'help' string is supplied for an option, it will still be
    listed in the help message.  To omit an option entirely, use
    the special value optik.SUPPRESS_HELP.

    Example:
      from optik import Option, OptionParser, SUPPRESS_HELP

      usage = "usage: %prog [options]"
      parser = OptionParser(usage, option_list=[
        make_option("-h", "--help", action="help"),
        make_option("-v", action="store_true", dest="verbose",
                    help="Be moderately verbose")
        make_option("--file", dest="filename",
                    help="Input file to read data from"),
        make_option("--secret", help=SUPPRESS_HELP)

    If Optik sees either "-h" or "--help" on the command line, it will
    print something like the following help message to stdout (assuming
    sys.argv[0] is "foo.py")

      usage: foo.py [options]

      options:
        -h, --help        Show this help message and exit
        -v                Be moderately verbose
        --file=FILENAME   Input file to read data from

    After printing the help message, Optik terminates your process
    with sys.exit(0).

  * version [required: none]
    Prints the version number supplied to the OptionParser to stdout
    and exits.  The version number is actually formatted and printed
    by the print_version() method of OptionParser.  Generally only
    relevant if the 'version' argument is supplied to the OptionParser
    constructor.


Option types
------------

Optik supports five option types out of the box: string, int, long,
float and complex.  (Of these, string, int, and float are the most
commonly used -- long and complex are there mainly for completeness.)
It's easy to add new option types by subclassing the Option class; see
extending.txt.

Arguments to string options are not checked or converted in any way: the
text on the command line is stored in the destination (or passed to the
callback) as-is.

Integer arguments are passed to int() to convert them to Python
integers.  If int() fails, so will Optik, although with a more useful
error message.  Internally, Optik raises OptionValueError in
optik.option.check_builtin(); at a higher level (in OptionParser) this
is caught and Optik terminates your program with a useful error message.

Likewise, float arguments are passed to float() for conversion, long
arguments to long(), and complex arguments to complex().  Apart from
that, they are handled identically to integer arguments.


Querying and manipulating your option parser
--------------------------------------------

Sometimes, it's useful to poke around your option parser and see what's
there.  OptionParser provides a couple of methods to help you out:

  has_option(opt_str : string) -> boolean

    Given an option string such as "-q" or "--verbose", returns true
    if the OptionParser has an option with that option string.

  get_option(opt_str : string) -> Option

    Returns the Option instance that implements the option string
    you supplied, or None if no options implement it.

  remove_option(opt_str : string)

    If the OptionParser has an option corresponding to 'opt_str',
    that option is removed.  If that option provided any other
    option strings, all of those option strings become invalid.

    If 'opt_str' does not occur in any option belonging to this
    OptionParser, raises ValueError.


Conflicts between options
-------------------------

If you're not careful, it's easy to define conflicting options:

  parser.add_option("-n", "--dry-run", ...)
  [...]
  parser.add_option("-n", "--noisy", ...)

(This is even easier to do if you've defined your own OptionParser
subclass with some standard options.)

On the assumption that this is usually a mistake, Optik 1.2 and later
raise an exception (OptionConflictError) by default when this happens.
Since this is an easily-fixed programming error, you shouldn't try to
catch this exception -- fix your mistake and get on with life.

Sometimes, you want newer options to deliberately replace the option
strings used by older options.  You can achieve this by calling
  parser.set_conflict_handler("resolve")
which instructs Optik to resolve option conflicts intelligently.

Here's how it works: every time you add an option, Optik checks for
conflicts with previously-added options.  If it finds any, it invokes
the conflict-handling mechanism you specify either to the OptionParser
constructor:
  parser = OptionParser(..., conflict_handler="resolve")
or via the set_conflict_handler() method.

The default conflict-handling mechanism is "error".  The only other one
is "ignore", which restores the (arguably broken) behaviour of Optik 1.1
and earlier.

Here's an example: first, define an OptionParser set to resolve
conflicts intelligently:
  parser = OptionParser(conflict_handler="resolve")

Now add all of our options:
  parser.add_option("-n", "--dry-run", ..., help="original dry-run option")
  [...]
  parser.add_option("-n", "--noisy", ..., help="be noisy")

At this point, Optik detects that a previously-added option is already
using the "-n" option string.  Since conflict_handler == "resolve", it
resolves the situation by removing "-n" from the earlier option's list
of option strings.  Now, "--dry-run" is the only way for the user to
activate that option.  If the user asks for help, the help message will
reflect that, eg.:

  options:
    --dry-run     original dry-run option
    [...]
    -n, --noisy   be noisy

Note that it's possible to whittle away the option strings for a
previously-added option until there are none left, and the user has no
way of invoking that option from the command-line.  In that case, Optik
removes that option completely, so it doesn't show up in help text or
anywhere else.  Eg. if we carry on with our existing OptionParser:
  parser.add_option("--dry-run", ..., help="new dry-run option")

At this point, the first -n/--dry-run option is no longer accessible, so
Optik removes it.  If the user asks for help, they'll get something like
this:

  options:
    [...]
    -n, --noisy   be noisy
    --dry-run     new dry-run option
