from typing import Any, Set, Union

def chk_none(name : str, value : Any) -> Any:
    if value is not None:
        msg = '{}({}) is not None.'
        raise AttributeError(msg.format(str(name), str(value)))
    return value

def chk_not_none(name : str, value : Any) -> Any:
    if value is None:
        msg = '{}({}) is None.'
        raise AttributeError(msg.format(str(name), str(value)))
    return value

def chk_type(name : str, value : Any, type_or_types : Union[type, Set[type]] = set()) -> Any:
    if not isinstance(value, type_or_types):
        msg = '{}({}) is of a wrong type({}). Accepted type_or_types({}).'
        raise AttributeError(msg.format(str(name), str(value), type(value).__name__, str(type_or_types)))
    return value

def chk_string(name, value, allow_empty=False) -> str:
    chk_not_none(name, value)
    chk_type(name, value, str)
    if allow_empty: return value
    if len(value) == 0:
        msg = '{}({}) string is empty.'
        raise AttributeError(msg.format(str(name), str(value)))
    return value

def chk_float(name, value, type_or_types=(int, float), min_value=None, max_value=None) -> float:
    chk_not_none(name, value)
    chk_type(name, value, type_or_types)
    if min_value is not None:
        chk_type(name, value, type_or_types)
        if value < min_value:
            msg = '{}({}) lower than min_value({}).'
            raise AttributeError(msg.format(str(name), str(value), str(min_value)))
    if max_value is not None:
        chk_type(name, value, type_or_types)
        if value > max_value:
            msg = '{}({}) greater than max_value({}).'
            raise AttributeError(msg.format(str(name), str(value), str(max_value)))
    return value

def chk_integer(name, value, min_value=None, max_value=None) -> int:
    return int(chk_float(name, value, type_or_types=int, min_value=min_value, max_value=max_value))

def chk_options(name, value, options):
    chk_not_none(name, value)
    if value not in options:
        msg = '{}({}) is not one of options({}).'
        raise AttributeError(msg.format(str(name), str(value), str(options)))
    return value
