Convert string variables to a specified type.

      >>> normalize('true', type='boolean')
      True
      >>> normalize('11', type='number')
      11
      >>> normalize('10.3', default=11.0)
      10.3

def normalize(value, default=None, type=None, raise_exception=False):
    """Convert string variables to a specified type.

      >>> normalize('true', type='boolean')
      True
      >>> normalize('11', type='number')
      11
      >>> normalize('10.3', default=11.0)
      10.3
    """
    NUMBER_RE = re.compile('^[-+]?(([0-9]+\.?[0-9]*)|([0-9]*\.?[0-9]+))$')
    if type is None and default is None:
        type = unicode_type
    elif type is None:
        type = type_(default)
    if type in str_types:
        if value is not None:
            if isinstance(value, unicode_type):
                return value
            elif py3 and isinstance(value, bytes_type):
                return value.decode('utf-8')
            return unicode_type(value)
        if default is None:
            if raise_exception:
                raise ValidationError('invalid string')
            else:
                return unicode_type()
    elif type in (bool, 'bool', 'boolean'):
        if value is not None:
            value = value.lower().strip()
            if value in ('1', 'true', 'yes', 'on'):
                return True
            elif value in ('0', 'false', 'no', 'off'):
                return False
        if default is None:
            if raise_exception:
                raise ValidationError('invalid boolean')
            else:
                return False
    elif type in (numbers.Number, 'number'):
        if value is not None:
            if value.isdigit():
                return int(value)
            elif NUMBER_RE.match(value):
                return eval(value)
        if default is None:
            if raise_exception:
                raise ValidationError('invalid number')
            else:
                return 0
    elif type in (int, 'int', 'integer'):
        try:
            return int(value)
        except Exception:
            if isinstance(value, basestring_type) and NUMBER_RE.match(value):
                return int(eval(value))
            if default is None:
                if raise_exception:
                    raise ValidationError('invalid number')
                else:
                    return 0
    elif type in (float, 'float'):
        if value is not None and NUMBER_RE.match(value):
            return float(value)
        if default is None:
            if raise_exception:
                raise ValidationError('invalid number')
            else:
                return 0.0
    return default