Optik: Advanced Usage

This is reference documentation. If you haven't read the Basic Usage tutorial document yet, 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")])

(make_option() is a factory function for creating Option instances; currently it is an alias for the Option constructor. A future version of Optik may split Option into several classes, and make_option() will pick the right class to instantiate. You should not instantiate Option directly.)

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:

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 option attributes, i.e. 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). 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 option attributes; see below.)

As you can see, most actions involve storing or updating a value somewhere. Optik always creates an instance of optik.Values (referred to as options) specifically for this purpose. Option arguments (and various other values) are stored as attributes of this object, according to the dest (destination) option attribute.

For example, when you call

parser.parse_args()

one of the first things Optik does is create the options object:

options = 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:

options.filename = "foo"

Clearly, the type and dest arguments are 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. Most actions have several relevant option attributes which you may specify to guide Optik's behaviour; a few have required attributes, which you must specify for any option using that action.

Option types

Optik has six built-in option types: string, int, long, choice, float and complex. If you need to add new option types, see Extending Optik.

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 from optik.option.check_builtin(); OptionParser catches this exception higher up and 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.

choice options are a subtype of string options. The choices option attribute (a sequence of strings) defines the set of allowed option arguments. optik.option.check_choice() compares user-supplied option arguments against this master list and raises OptionValueError if an invalid string is given.

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 supplied option string, 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.)

Every time you add an option, Optik checks for conflicts with existing options. If it finds any, it invokes the current conflict-handling mechanism. You can set the conflict-handling mechanism either in the constructor:

parser = OptionParser(..., conflict_handler="...")

or with a separate call:

parser.set_conflict_handler("...")

The available conflict-handling mechanisms are:

error (default)
assume option conflicts are a programming error and raise OptionConflictError
resolve
resolve option conflicts intelligently (see below)
ignore
ignore the problem and behave unpredictably (only present for compatibility with Optik 1.1 and earlier)

Here's an example: first, define an OptionParser that resolves 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 is "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, e.g.:

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. E.g. 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