# user_interface module

As writing code to handle error-checked input or to present functions to execute to the user is boring and error-prone, I wrote a module to automate these tasks:

user_interface.py

def general_input(prompt="", type_=str, min_=None, max_=None,
max_length=None, set_=None, cap_sensitive=True,
help_=lambda: 0):
"""
Takes care of input validation, by diplaying meaningful
messages to the user in case of invalid input.

@ prompt: The text to be shown to the user.
@ type_: The type the input must be convertible to. (And will be converted to).
@ max_length: The maximum length of the input.
@ set_: The set of things the input must in. (This may be a range object or any iterable).
@ cap_sensitive: If False the input will be lowercased. (Defult True)
@ help_: What to do when the user types in help
"""
while True:
input_ = input(prompt)
input_ = input_ if cap_sensitive else input_.lower()
if input_ == "help":
help_()
continue
try:
if not type_:
type_ = type(input_)
input_ = type_(input_)
except ValueError:
print("Expected input of type {} but got {}".format(
type_, type(input_)))
continue
if max_length and len(input_) > max_length:
print("Input is too long, the max length allowed is {}".format(
max_length))
continue
if set_ and input_ not in set_:
# Fixing that the last item in ranges is exclusive (weird for normal users)
to_print_set = None
if type(set_) == range:
to_print_set = range(min(set_), max(set_))
print("Input is not in the set of possible inputs, enter one of {}".format(
to_print_set or set_))
continue
return input_

"""
Allows for easy presentation to the user of functions, also
allowing him to get fast help.
"""
functions = list(sorted(functions, key=lambda fun: fun.__name__))
for index, func in enumerate(functions):
print("{} - {}".format(
index + 1, func.__name__))
def help_():
function_to_be_explained = general_input("Which function do you want help on? ",
type_=int, set_=range(0,len(functions))) - 1
help(functions[function_to_be_explained])

user_choice = general_input("Which function do you want to execute? (Type help for help). ",
type_=int, set_=range(0,len(functions)+1),
help_= help_) - 1
print(functions[user_choice](eval(input("Comma separated args for {}: ".format(
functions[user_choice].__name__))))); print()

"""
Shows a menu containing all the functions in a module
"""
priv_cond = lambda fun: fun.__name__.startswith('_') if not private_shown else False
menu([i for i in module.__dict__.values() if type(i) == type(lambda:0) and not priv_cond(i)])


There's something in here that doesn't seem to make a lot of sense:

    try:
if not type_:
type_ = type(input_)
input_ = type_(input_)
except ValueError:
print("Expected input of type {} but got {}".format(
type_, type(input_)))
continue


If type is falsy, get the type of the input and re-cast the input? That seems unnecessary. And in this case the whole type validation seems unnecessary. You could skip the validation of the specified type is falsy.

A very minor thing, the default start of a range is 0, so you could just skip that.