From 1e154aebd311348b5e6d3bc3047366f3b7be4665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Papin?= Date: Tue, 23 May 2023 23:37:49 +0200 Subject: [PATCH] FEATURE: Add DataValidator class for validating datetime inputs --- InquirerPy/validator.py | 40 +++++++++++++++++++++++++++++++++++++++ docs/pages/validator.md | 42 +++++++++++++++++++++++++++++++++++++++++ tests/test_validator.py | 18 ++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/InquirerPy/validator.py b/InquirerPy/validator.py index aece4fd..e0bab27 100644 --- a/InquirerPy/validator.py +++ b/InquirerPy/validator.py @@ -1,5 +1,6 @@ """Module contains pre-built validators.""" import re +from datetime import datetime from pathlib import Path from typing import Optional @@ -10,6 +11,7 @@ "EmptyInputValidator", "PasswordValidator", "NumberValidator", + "DateValidator" ] @@ -163,3 +165,41 @@ def validate(self, document) -> None: raise ValidationError( message=self._message, cursor_position=document.cursor_position ) + + +class DateValidator(Validator): + """:class:`~prompt_toolkit.validation.Validator` to validate if input is a valid date. + + Args: + message: Error message to display in the validatation toolbar when validation failed. + format: Specify the desired date format. + """ + + def __init__( + self, + message: str = "Invalid date format", + formats: list[str] = ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"], + ) -> None: + self._message = message + self._formats = formats + + def validate(self, input_date) -> None: + """Check if the user's date input is valid and well-formatted. + + This method is used internally by `prompt_toolkit `_. + + See Also: + https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html?highlight=validator#input-validation + + """ + + for form in self._formats: + try: + return datetime.strptime(input_date.text, form) + except ValueError: + continue + + raise ValidationError( + message=self._message, + cursor_position=input_date.cursor_position, + ) \ No newline at end of file diff --git a/docs/pages/validator.md b/docs/pages/validator.md index e1d80db..ba2dad3 100644 --- a/docs/pages/validator.md +++ b/docs/pages/validator.md @@ -308,3 +308,45 @@ result = inquirer.text(message="Age:", validate=NumberValidator()).execute() ``` + +### DateValidator + +```{eval-rst} +.. autoclass:: InquirerPy.validator.DateValidator + :noindex: +``` + +
+ Classic Syntax + +```python +from InquirerPy import prompt +from InquirerPy.validator import DateValidator + +result = prompt( + [ + { + "type": "input", + "message": "Date of birth:", + "validate": DateValidator( + message="Invalid date format", + formats=["%Y-%m-%d"] + ), + } + ] +) +``` + +
+ +
+ Alternate Syntax + +```python +from InquirerPy import inquirer +from InquirerPy.validator import NumberValidator + +result = inquirer.text(message="Date of birth:", validate=DateValidator()).execute() +``` + +
\ No newline at end of file diff --git a/tests/test_validator.py b/tests/test_validator.py index 40cad21..1c83561 100644 --- a/tests/test_validator.py +++ b/tests/test_validator.py @@ -73,3 +73,21 @@ def test_numberValidator(self): self.assertRaises(ValidationError, validator.validate, self.document) validator = NumberValidator(float_allowed=True) self.execute_success_case(validator, "test_numberValidator") + + def test_dateValidator(self): + validator = DateValidator() + self.document._text = "2042-04-02" + self.execute_success_case(validator, "test_dateValidator") + self.document._text = "0001-12-12" + self.execute_success_case(validator, "test_dateValidator") + self.document._text = "11-12-11" + self.assertRaises(ValidationError, validator.validate, self.document) + self.document._text = "1212-12-12 12:12:12" + self.execute_success_case(validator, "test_dateValidator") + self.document._text = "1212-12-12T12:12:12" + self.execute_success_case(validator, "test_dateValidator") + self.document._text = "2023-02-29" + self.assertRaises(ValidationError, validator.validate, self.document) + validator = DateValidator(formats=["%d/%m/%Y"]) + self.document._text = "28/02/2023" + self.execute_success_case(validator, "test_dateValidator") \ No newline at end of file