def take_settings_menu_input() -> Optional[bool]: """ Takes input and runs chosen action. Loop broken when chosen action completes, returning None and returning to the loop in run_settings_menu, which will reprint the menu options. If '0' is entered to return to the main menu, the loop returns True, triggering the flag in run_settings_menu, breaking that loop, and returning to the loop in run_main_menu. :return: None or True """ possible_options = { '1': call_set_default_chart_save_location, '2': call_set_database_backend, # Future option. '0': return_to_main_menu, } chosen_option = get_user_input( prompt='>>> ', validation=lambda choice: choice in possible_options, validation_error_msg="Invalid input.") possible_options[chosen_option]() if chosen_option == '0': # User selects to return to main menu. return True # else: return None
def take_main_menu_input() -> Optional[bool]: """ Takes input and runs chosen action. Loop broken when chosen action completes, returning None and returning to the loop in run_main_menu, which will reprint the menu options. If 'Q' is entered to quit app, returns True, triggering the flag in run_main_menu, breaking that loop, and proceeding to app quit/shutdown code. possible_options must be type hinted or mypy will complain about: "error: Cannot call function of unknown type" :return: None or True """ possible_options: Dict[str, Callable] = { '1': create_classlist, '2': edit_class_data, '3': new_chart, '9': run_settings_menu, } def input_validator(user_input: str) -> bool: return user_input in possible_options or user_input.upper() == 'Q' chosen_option = get_user_input(prompt='>>> ', validation=input_validator, validation_error_msg='Invalid input.') if chosen_option.upper() == 'Q': return True # Quit app. possible_options[chosen_option]() return None
def take_database_choice_input() -> Union[str, bool]: """ Take user choice of database backends. Return string name of the chosen backend, or False if user does not choose a backend. Alternate implementation that pulls the choice list from those enabled in the persistence.database_functions module: from dionysus_app.persistence.database_functions import database_backends possible_options = dict(enumerate(database_backends, start=1)) :return: str or False """ possible_options = { '1': 'JSON', '2': 'SQLite', '0': False, # Cancel/return to menu. } chosen_option = get_user_input( prompt='>>> ', validation=lambda user_input: user_input in possible_options, validation_error_msg="Invalid input.") return possible_options[chosen_option] # type: ignore
def take_chart_name() -> str: """ Ask user for chart name. Ask again if name is essentially blank/whitespace/punctuation. :return: str """ chart_name = get_user_input( prompt='Please enter a chart name/title: ', validation=lambda name: not input_is_essentially_blank(name), validation_error_msg='Please enter a valid chart name.') return chart_name
def test_get_user_input(self, capsys, prompt, validation_function, error_message, inputs): with patch('builtins.input', side_effect=list(inputs)): assert get_user_input(prompt, validation_function, error_message) == inputs[-1] captured = capsys.readouterr() print(captured) # Check error message/s if isinstance(error_message, str): for attempt in inputs[:-1]: assert f'{error_message}\n' in captured.out elif callable(error_message): for attempt in inputs[:-1]: assert f'{error_message(attempt)}\n' in captured.out
def take_classlist_name_input() -> str: """ Prompts user for classlist name. Repeats until user provide valid classlist name. :return: str """ classlist_name = get_user_input( prompt='Please enter a name for the class: ', validation=lambda name: not input_is_essentially_blank(name) and not definitions.DATABASE.class_name_exists(clean_for_filename(name)), validation_error_msg=lambda name: None if input_is_essentially_blank( name) else 'A class with this name already exists.') return clean_for_filename(classlist_name)
def take_student_name_input(the_class: Class) -> str: """ Prompts user to enter a valid student name. Prompts user for student name, checks if student name is a valid name, or is already in the class, prompting to enter a different name if this is the case. :param the_class: Class object :return: str """ invalid_input_msg = 'Please enter a valid student name.' student_exists_msg = "This student is already a member of the class." student_name = get_user_input( prompt="Enter student name, or 'end', and hit enter: ", validation=lambda name: not input_is_essentially_blank( name) and name not in the_class, validation_error_msg=lambda name: student_exists_msg if name in the_class else invalid_input_msg) return student_name