import gettext import locale from numbers import Number from typing import overload # mypy and pylint don't work well with gettext.install lang, _enc = locale.getlocale() lang = lang or 'en' _ = gettext.translation('python_misc', localedir='locale', languages=[lang, lang.split('_')[0], 'en'], fallback=True).gettext def wait_for_enter() -> None: input(_('\nPress ENTER to continue...\n')) def print_input_error(message: str) -> None: print(_('Error: {0}. Try again...').format(message)) @overload def read_number[T: Number](prompt: str, _type: type[T]) -> T: ... @overload def read_number(prompt: str = ...) -> float: ... def read_number(prompt: str = _('Enter the number: '), _type: type = float): while True: try: return _type(input(prompt)) except ValueError: print_input_error(_('not a number')) @overload def read_nonzero_number[T: Number](prompt: str, _type: type[T]) -> T: ... @overload def read_nonzero_number[T: Number](prompt: str) -> float: ... def read_nonzero_number(prompt: str = _('Enter the number (cannot be zero): '), _type: type = float): while True: number: Number = read_number(prompt, _type) if number != 0: return number print_input_error('number is equal to zero') @overload def read_number_from_range[T: int | float](lower: T, upper: T, _type: type[T]) -> T: ... @overload def read_number_from_range[T: int | float](lower: T, upper: T) -> float: ... def read_number_from_range[T: int | float](lower: T, upper: T, _type: type = float): prompt = _('Enter the number between {0} and {1}: ').format(lower, upper) while True: number = read_number(prompt) if lower <= number <= upper: return number print_input_error(_('number is out of range'))