| """Module contains pre-built validators.""" |
| import re |
| from pathlib import Path |
| from typing import Optional |
|
|
| from prompt_toolkit.validation import ValidationError, Validator |
|
|
| __all__ = [ |
| "PathValidator", |
| "EmptyInputValidator", |
| "PasswordValidator", |
| "NumberValidator", |
| ] |
|
|
|
|
| class NumberValidator(Validator): |
| """:class:`~prompt_toolkit.validation.Validator` to validate if input is a number. |
| |
| Args: |
| message: Error message to display in the validatation toolbar when validation failed. |
| float_allowed: Allow input to contain floating number (with decimal). |
| """ |
|
|
| def __init__( |
| self, message: str = "Input should be a number", float_allowed: bool = False |
| ) -> None: |
| self._message = message |
| self._float_allowed = float_allowed |
|
|
| def validate(self, document) -> None: |
| """Check if user input is a valid number. |
| |
| This method is used internally by `prompt_toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/>`_. |
| |
| See Also: |
| https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html?highlight=validator#input-validation |
| """ |
| try: |
| if self._float_allowed: |
| float(document.text) |
| else: |
| int(document.text) |
| except ValueError: |
| raise ValidationError( |
| message=self._message, cursor_position=document.cursor_position |
| ) |
|
|
|
|
| class PathValidator(Validator): |
| """:class:`~prompt_toolkit.validation.Validator` to validate if input is a valid filepath on the system. |
| |
| Args: |
| message: Error message to display in the validatation toolbar when validation failed. |
| is_file: Explicitly check if the input is a valid file on the system. |
| is_dir: Explicitly check if the input is a valid directory/folder on the system. |
| """ |
|
|
| def __init__( |
| self, |
| message: str = "Input is not a valid path", |
| is_file: bool = False, |
| is_dir: bool = False, |
| ) -> None: |
| self._message = message |
| self._is_file = is_file |
| self._is_dir = is_dir |
|
|
| def validate(self, document) -> None: |
| """Check if user input is a filepath that exists on the system based on conditions. |
| |
| This method is used internally by `prompt_toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/>`_. |
| |
| See Also: |
| https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html?highlight=validator#input-validation |
| """ |
| path = Path(document.text).expanduser() |
| if self._is_file and not path.is_file(): |
| raise ValidationError( |
| message=self._message, |
| cursor_position=document.cursor_position, |
| ) |
| elif self._is_dir and not path.is_dir(): |
| raise ValidationError( |
| message=self._message, |
| cursor_position=document.cursor_position, |
| ) |
| elif not path.exists(): |
| raise ValidationError( |
| message=self._message, |
| cursor_position=document.cursor_position, |
| ) |
|
|
|
|
| class EmptyInputValidator(Validator): |
| """:class:`~prompt_toolkit.validation.Validator` to validate if the input is empty. |
| |
| Args: |
| message: Error message to display in the validatation toolbar when validation failed. |
| """ |
|
|
| def __init__(self, message: str = "Input cannot be empty") -> None: |
| self._message = message |
|
|
| def validate(self, document) -> None: |
| """Check if user input is empty. |
| |
| This method is used internally by `prompt_toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/>`_. |
| |
| See Also: |
| https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html?highlight=validator#input-validation |
| """ |
| if not len(document.text) > 0: |
| raise ValidationError( |
| message=self._message, |
| cursor_position=document.cursor_position, |
| ) |
|
|
|
|
| class PasswordValidator(Validator): |
| """:class:`~prompt_toolkit.validation.Validator` to validate password compliance. |
| |
| Args: |
| message: Error message to display in the validatation toolbar when validation failed. |
| length: The minimum length of the password. |
| cap: Password should include at least one capital letter. |
| special: Password should include at least one special char "@$!%*#?&". |
| number: Password should include at least one number. |
| """ |
|
|
| def __init__( |
| self, |
| message: str = "Input is not compliant with the password constraints", |
| length: Optional[int] = None, |
| cap: bool = False, |
| special: bool = False, |
| number: bool = False, |
| ) -> None: |
| password_pattern = r"^" |
| if cap: |
| password_pattern += r"(?=.*[A-Z])" |
| if special: |
| password_pattern += r"(?=.*[@$!%*#?&])" |
| if number: |
| password_pattern += r"(?=.*[0-9])" |
| password_pattern += r"." |
| if length: |
| password_pattern += r"{%s,}" % length |
| else: |
| password_pattern += r"*" |
| password_pattern += r"$" |
| self._re = re.compile(password_pattern) |
| self._message = message |
|
|
| def validate(self, document) -> None: |
| """Check if user input is compliant with the specified password constraints. |
| |
| This method is used internally by `prompt_toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/>`_. |
| |
| See Also: |
| https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html?highlight=validator#input-validation |
| """ |
| if not self._re.match(document.text): |
| raise ValidationError( |
| message=self._message, cursor_position=document.cursor_position |
| ) |
|
|