piranha/opster — pull request #33 by oscarbenjamin (2012-05-21 23:31:49+00:00)
Title: Add support for arbitrary option types

This patch adds support and 1 test for using arbitrary option types in opster. Previous version of opster supported this, although I'm not sure if it was intentional since it was never documented.

Essentially, opster can create option instances of any type by doing ```optval = type(optdefault)(optarg)```. This works for LiteralOption, IntOption and FloatOption (making each of those types redundant if it is the default behaviour for BaseOption). Allowing this in general for BaseOption and allowing BaseOption to match against object ensures that arbitrary types can be supported as option types provided the type can be created from a string. For example, we can have a script like:

#!/usr/bin/env python

from decimal import Decimal
from fractions import Fraction
import opster

@opster.command()
def main(x=('f', Decimal('1'), 'decimal number'),
y=('h', Fraction('1/2'), 'fraction number')):
print x, type(x)
print y, type(y)

main.command()

Then the script can be used like

$ ./script.py --x=.3 --y='9/16'
0.3
9/16

The other implication of doing this on python 2.x is that if the default option values was a unicode string that the input argument will be converted to a unicode string by opster. Perhaps it would be better to add the `LiteralOption` in again for clarity even if it is redundant (although the previous version would have ignored the type of unicode arguments when processing option values).

With this patch only the types `bool`, `list`, `dict` and `Callable` are special cased.

Is this desirable behaviour for opster? I used it with `decimal.Decimal` a few times since it worked with previous opster versions, but I don't think it was ever documented (although I think the code in the old version of `process()` was written with this kind of usage in mind).