Source code for questions.validators

import re
from typing import Any
from typing import Dict

from email_validator import EmailNotValidError
from email_validator import validate_email
from simpleeval import EvalWithCompoundTypes as Evaluator
from simpleeval import InvalidExpression

from .questions import Validator


[docs]class ValidationError(Exception): """ Validation error exception, for use by Form.update_object. """
[docs]def text_validator(validator: Validator, value: Any, form_data: Dict[str, Any]): """Validate length of a text value, and whether digits are allowed. :param validator: The validator instance for the current question. :param value: The value to be validated. :param form_data: The dictionary containing from data entered for current form. :Returns: If validation passes, :data:`True`, else :data:`False`. """ max_length = int(validator.max_length) min_length = int(validator.min_length) allow_digits = validator.allow_digits result = True value = str(value) length = len(value) if length < min_length or max_length > 0 and length > max_length: result = False if not allow_digits: for number in range(10): if str(number) in value: result = False return result
[docs]def numeric_validator(validator: Validator, value: Any, form_data: Dict[str, Any]): """Validate if number value is within set limits. :param validator: The validator instance for the current question. :param value: The value to be validated. :param form_data: The dictionary containing from data entered for current form. :Returns: If validation passes, :data:`True`, else :data:`False`. """ max_value = float(validator.max_value) min_value = float(validator.min_value) result = True value = float(value) if value < min_value or max_value > 0 and value > max_value: result = False return result
[docs]def email_validator(validator: Validator, value: Any, form_data: Dict[str, Any]): """Validate if value is a valid email address. :param validator: The validator instance for the current question. :param value: The value to be validated. :param form_data: The dictionary containing from data entered for current form. :Returns: If validation passes, :data:`True`, else :data:`False`. """ result = True try: validate_email(value) except EmailNotValidError: result = False return result
[docs]def regex_validator(validator: Validator, value: Any, form_data: Dict[str, Any]): """Validate if value matches regular expression. :param validator: The validator instance for the current question. :param value: The value to be validated. :param form_data: The dictionary containing from data entered for current form. :Returns: If validation passes, :data:`True`, else :data:`False`. """ regex = validator.regex regex = re.compile(regex) return regex.match(value) is not None
[docs]def expression_validator(validator: Validator, value: Any, form_data: Dict[str, Any]): """Validate if expression associated with value is true. :param validator: The validator instance for the current question. :param value: The value to be validated. :param form_data: The dictionary containing from data entered for current form. :Returns: If validation passes, :data:`True`, else :data:`False`. """ expression = validator.expression result = True if expression: expression = expression.replace("{", "").replace("}", "") expression = expression.replace(" empty", " in [[], {}]") expression = expression.replace(" notempty", " not in [[], {}]") expression = expression.replace(" anyof ", " in ") try: evaluator = Evaluator(names=form_data) result = evaluator.eval(expression) is True except (ValueError, TypeError, SyntaxError, KeyError, InvalidExpression): result = False return result
VALIDATORS = { "text": text_validator, "numeric": numeric_validator, "email": email_validator, "regex": regex_validator, "expression": expression_validator, }
[docs]def call_validator(validator: Validator, value: Any, form_data: Dict[str, Any]): """Call correct validation method depending on validator type. :param validator: The validator instance for the current question. :param value: The value to be validated. :param form_data: The dictionary containing from data entered for current form. :Returns: If validation passes, :data:`True`, else :data:`False`. """ validator_method = VALIDATORS[validator.kind] return validator_method(validator, value, form_data)