Verify string lengths when creating model objects

This commit is contained in:
Marcus Lindvall 2019-11-19 16:24:10 +01:00
parent f9686c5306
commit 5d1b5f90ac
2 changed files with 57 additions and 0 deletions

View file

@ -17,6 +17,7 @@ from sqlservice import ModelBase, as_declarative
from pyjeeves import logging from pyjeeves import logging
from . import db from . import db
from .ext import InstallValidatorListeners
logger = logging.getLogger("PyJeeves." + __name__) logger = logging.getLogger("PyJeeves." + __name__)
@ -37,6 +38,7 @@ except OperationalError as e:
class RawBaseModel(ModelBase): class RawBaseModel(ModelBase):
""" Generalize __init__, __repr__ and to_json """ Generalize __init__, __repr__ and to_json
Based on the models columns , ForetagKod=1""" Based on the models columns , ForetagKod=1"""
__sa_instrumentation_manager__ = InstallValidatorListeners
__to_dict_filter__ = [] __to_dict_filter__ = []
__to_dict_only__ = () __to_dict_only__ = ()

55
pyjeeves/models/ext.py Normal file
View file

@ -0,0 +1,55 @@
from sqlalchemy.ext.instrumentation import InstrumentationManager
# from sqlalchemy.orm.interfaces import AttributeExtension
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
class InstallValidatorListeners(InstrumentationManager):
def post_configure_attribute(self, 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__, self.col_name, len(value), self.max_length))
return value