from sqlalchemy.orm import ColumnProperty from sqlalchemy.types import String from sqlalchemy import event class Error(Exception): """Base class for exceptions in this module.""" pass class ValidationError(Error): pass class JeevesDBError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, field, message): super().__init__(message) self.field = field self.message = message def install_validator_listner(class_, key, inst): """Add validators for any attributes that can be validated.""" prop = inst.prop # Only interested in simple columns, not relations if isinstance(prop, ColumnProperty) and len(prop.columns) == 1: col = prop.columns[0] # if we have string column with a length, create a length validator listner if isinstance(col.type, String) and col.type.length: event.listen( getattr(class_, key), 'set', LengthValidator( col.name, col.type.length), retval=True) class LengthValidator(): def __init__(self, col_name, max_length): self.col_name = col_name self.max_length = max_length def __call__(self, state, value, oldvalue, initiator): if len(value) > self.max_length: raise ValidationError( "%s.%s: Length %d exceeds allowed %d" % ( state.__class__.__name__, state.__class__._map_columns(self.col_name), len(value), self.max_length)) return value