6.20.5.1 Adding new types
Description: Adding new types
Keywords: lib

###
6.20.5.1 Adding new types

To add new types, you need to define your own subclass of `optparse`'s `Option` class. This class has a couple of attributes that define `optparse`'s types: `TYPES` and `TYPE_CHECKER`.

`TYPES` is a tuple of type names; in your subclass, simply define a new tuple `TYPES` that builds on the standard one.

`TYPE_CHECKER` is a dictionary mapping type names to type-checking functions. A type-checking function has the following signature:

    def check_foo (option : Option, opt : string, value : string)
                   -> foo

You can name it whatever you like, and make it return any type you like. The value returned by a type-checking function will wind up in the `OptionValues` instance returned by `OptionParser.parse_args()`, or be passed to callbacks as the value parameter.

Your type-checking function should raise `OptionValueError` if it encounters any problems. `OptionValueError` takes a single string argument, which is passed as-is to `OptionParser`'s `error()` method, which in turn prepends the program name and the string ``error:'' and prints everything to stderr before terminating the process.

Here's a silly example that demonstrates adding a ``complex'' option type to parse Python-style complex numbers on the command line. (This is even sillier than it used to be, because `optparse` 1.3 adds built-in support for complex numbers [purely for completeness], but never mind.)

First, the necessary imports:

    from copy import copy
    from optparse import Option, OptionValueError

You need to define your type-checker first, since it's referred to later (in the `TYPE_CHECKER` class attribute of your `Option` subclass):

    def check_complex (option, opt, value):
        try:
            return complex(value)
        except ValueError:
            raise OptionValueError(
                "option %s: invalid complex value: %r" % (opt, value))

Finally, the `Option` subclass:

    class MyOption (Option):
        TYPES = Option.TYPES + ("complex",)
        TYPE_CHECKER = copy(Option.TYPE_CHECKER)
        TYPE_CHECKER["complex"] = check_complex

(If we didn't make a `copy()` of `Option.TYPE_CHECKER`, we would end up modifying the `TYPE_CHECKER` attribute of `optparse`'s Option class. This being Python, nothing stops you from doing that except good manners and common sense.)

That's it! Now you can write a script that uses the new option type just like any other `optparse`-based script, except you have to instruct your `OptionParser` to use `MyOption` instead of `Option`:

    parser = OptionParser(option_class=MyOption)
    parser.add_option("-c", action="store", type="complex", dest="c")

Alternately, you can build your own option list and pass it to `OptionParser`; if you don't use `add_option()` in the above way, you don't need to tell `OptionParser` which option class to use:

    option_list = [MyOption("-c", action="store", type="complex", dest="c")]
    parser = OptionParser(option_list=option_list)