def normalize_text(value: str, field_name: str, max_length: int = 80) -> str: """Strip and validate a required text value.""" text = value.strip() if not text: raise ValueError(f"Поле «{field_name}» не должно быть пустым.") if len(text) > max_length: raise ValueError( f"Поле «{field_name}» должно быть не длиннее {max_length} символов." ) return text def parse_float(value: str, field_name: str) -> float: """Parse a float from Russian-style user input.""" prepared = value.strip().replace(" ", "").replace(",", ".") try: number = float(prepared) except ValueError as error: raise ValueError(f"Поле «{field_name}» должно быть числом.") from error return number def parse_positive_float(value: str, field_name: str) -> float: """Parse a strictly positive float.""" number = parse_float(value, field_name) if number <= 0: raise ValueError(f"Поле «{field_name}» должно быть больше нуля.") return number def parse_billing_day(value: str) -> int: """Parse subscription billing day.""" try: day = int(value.strip()) except ValueError as error: raise ValueError("День списания должен быть целым числом от 1 до 31.") from error if not 1 <= day <= 31: raise ValueError("День списания должен быть в диапазоне от 1 до 31.") return day