3
\$\begingroup\$

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_
def menu(functions):
 """
 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()
def menu_for_module(module, private_shown=False):
 """
 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)])
asked Jun 18, 2015 at 13:26
\$\endgroup\$
1

1 Answer 1

3
\$\begingroup\$

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.

answered Jun 18, 2015 at 15:46
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.