# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8

__all__ = ('vprop', 'vsyn',
           )

from sqlalchemy.sql import operators
from sqlalchemy.orm import synonym
from sqlalchemy.orm.properties import ColumnProperty

def vprop(name, validator):
    u"""Dans un modèle, créer une propriété validée, e.g:

        class MyModel(Model):
            value =  vprop('_value', unicodeF.parse)

            @classmethod
            def __map(cls, mapper, tables):
                mymodels = tables.mymodels
                properties = dict(value=vsyn('_value', unicodeF.parse))
                return mapper(MyModel, mymodels, properties=properties), mymodels

    Dans cet exemple, value est une valeur en unicode. Notez qu'il faut définir
    le synonyme dans le mapping.
    """
    def get_value(self): return getattr(self, name)
    def set_value(self, value): setattr(self, name, validator(value))
    return property(get_value, set_value)

def vsyn(name, validator, **kw):
    class Comparator(ColumnProperty.Comparator):
        def __lt__(self, other): return self.operate(operators.lt, validator(other))
        def __le__(self, other): return self.operate(operators.le, validator(other))
        def __eq__(self, other): return self.operate(operators.eq, validator(other))
        def __ne__(self, other): return self.operate(operators.ne, validator(other))
        def __gt__(self, other): return self.operate(operators.gt, validator(other))
        def __ge__(self, other): return self.operate(operators.ge, validator(other))
        def in_(self, other): return self.operate(operators.in_op, map(validator, other))
        def __add__(self, other): return self.operate(operators.add, validator(other))
        def __sub__(self, other): return self.operate(operators.sub, validator(other))
        def __radd__(self, other): return self.reverse_operate(operators.add, validator(other))
        def __rsub__(self, other): return self.reverse_operate(operators.sub, validator(other))
    return synonym(name, map_column=True, comparator_factory=Comparator, **kw)
