def sanitize_input(prompt, type_=None, min_=None, max_=None, range_=None):
    """
    Sanitizes user input.

    Loops until a value matching all criteria is entered.

    Credit to : http://stackoverflow.com/a/23294659/2758732 (MIT License)

    :param prompt: The message to show before asking for the input.
    :param type_: The type used to parse user input.
                  May also be a function who raises `ValueError`
                  if an error occurs.
    :param min_: The minimum value.
                 The input is parsed and compared to this parameter with `<`.
    :param max_: The maximum value.
                 The input is parsed and compared to this parameter with `>`.
    :param range_: The range the input should be in.
                   May be any class that implements `__contains__`.
    :return: The sanitized value.
    """
    if min_ is not None and max_ is not None and max_ < min_:
        raise ValueError('min_ must be less than or equal to max_.')
    while True:
        ui = input(prompt)
        if type_ is not None:
            try:
                ui = type_(ui)
            except ValueError:
                print('Input type must be {0}.'.format(type_.__name__))
                continue
        if max_ is not None and ui > max_:
            print('Input must be less than or equal to {0}.'.format(max_))
        elif min_ is not None and ui < min_:
            print('Input must be greater than or equal to {0}.'.format(min_))
        elif range_ is not None and ui not in range_:
            if isinstance(range_, range):
                template = 'Input must be between {0.start} and {0.stop}.'
                print(template.format(range_))
            else:
                template = 'Input must be {0}.'
                if len(range_) == 1:
                    print(template.format(*range_))
                else:
                    print(template.format(' or '.join((', '.join(map(str,
                        range_[:-1])), str(range_[-1])))))
        else:
            return ui
