def is_valid(value, cast_fn, expected_data_type, allow_none=False):
    """
    Checks whether a value can be converted using the cast_fn function.

    Args:
        value: Value to be considered
        cast_fn: Function used to determine the validity, should throw an
                 exception if it cannot
        expected_data_type: string name of the expected data
        allow_none: Boolean determining if none is valid
    Returns:
        tuple:
            **valid (boolean)**: whether it could be casted
            **msg (string)**: Msg reporting what happen
    """
    try:

        # Check for a non-none value
        if str(value).lower() != 'none':
            value = cast_fn(value)
            valid = True
            msg = None

        # Handle the error for none when not allowed
        elif not allow_none and str(value).lower() == 'none':
            valid = False
            msg = 'Value cannot be None'

        # Report all good for nones when they are allowed
        else:
            valid = True
            msg = None

    # Report an exception when the casting goes bad.
    except Exception:
        valid = False
        msg = "Expecting {0} received {1}".format(expected_data_type,
                                                  type(value).__name__)
    return valid, msg