Source code for sqlalchemy_unchained.validation

try:
    from speaklater import _LazyString
except ImportError:
    _LazyString = object

from typing import *

from .utils import title_case


class BaseValidationError(Exception):
    pass


[docs]class ValidationError(BaseValidationError): """ Holds a validation error for a single column of a model. """ def __init__(self, msg: str = None, model=None, column=None, validator=None): """ The constructor for validation errors. :param msg: The error message. If ``validator`` is provided and it implements ``get_message``, that will take precedence over this parameter. :param model: The model this validation error is for. :param column: The :class:`~sqlalchemy.Column` this validation error is for. :param validator: The validator instance that raised this validation error. """ super().__init__(msg) self.msg = msg """ The error message. If ``validator`` is provided and it implements ``get_message``, that will take precedence over this value. """ self.model = model """ The model this validation error is for. """ self.column = column """ The :class:`~sqlalchemy.Column` this validation error is for. """ self.validator = validator """ The validator instance that raised this validation error. """ def __str__(self): if self.validator and hasattr(self.validator, 'get_message'): return self.validator.get_message(self) return super().__str__()
[docs]class ValidationErrors(BaseValidationError): """ Holds validation errors for an entire model. """ def __init__(self, errors: Dict[str, List[str]]): super().__init__() self.errors = errors """ A dictionary of errors, where the keys are column names, and the values are lists of error messages for each column. """ def __str__(self): return '\n'.join([k + ': ' + str(e) for k, e in self.errors.items()])
[docs]class BaseValidator: """ Base class for column validators in SQLAlchemy Unchained. You should supply the error message to the constructor, and implement your validation logic in :meth:`~sqlalchemy_unchained.BaseValidator.__call__`:: from sqlalchemy_unchained import BaseValidator, ValidationError class NameRequired(BaseValidator): def __init__(msg='Name is required.'): super().__init__(msg=msg) def __call__(self, value): super().__call__(value) if not value: raise ValidationError(validator=self) class YourModel(db.Model): name = db.Column(db.String, nullable=False, info=dict( validators=[NameRequired])) """ def __init__(self, msg=None): super().__init__() self.msg = msg """ The message for this validator. """ self.value = None def __call__(self, value): """ Implement validation logic here. Raise :class:`~sqlalchemy_unchained.ValidationError` if validation does not pass. """ self.value = value
[docs] def get_message(self, e: ValidationError): """ Returns the message for this validation error. By default we just return ``self.msg``, but you can override this method if you need to customize the message. """ return self.msg
[docs]class Required(BaseValidator): """ A validator to require data. """ def __call__(self, value): super().__call__(value) if value is None or isinstance(value, str) and not value: raise ValidationError(validator=self) def get_message(self, e: ValidationError): if self.msg: if isinstance(self.msg, str): return self.msg elif isinstance(self.msg, _LazyString): return str(self.msg) return title_case(e.column) + ' is required.'
__all__ = [ 'BaseValidationError', 'BaseValidator', 'Required', 'ValidationError', 'ValidationErrors', ]