Thank you, i got it working now. For future reference:

Before creating a sa class with something like:

    type(typename, (Base,), classdict)

I first create the classdict in which I define columns, __tablename__,
etc, and validators (relationships I add later).

The validators i create(using a subclass of dict as classdict in the
type() call, and typedef being an object holding the definition to be
used to create a sa class/table) with:

    def createValidator(self, typedef):
            # get names of attributes to be validated:
            names = [attr.name for attr in typedef.attributes \
                       if attr.validates()]
            #create validator method from validating method in the
attr
            #definition in typedef:
            def validator(obj, name, value):
                return typedef[name].validate(value)
            #turn into sa "@validate" descriptor (i don't get the
            #mechanics completely, but still):
            validates(*names)(validator)
            #add to classdict
            self['validator'] = validator

Hope this helps someone, open to questions ...

Cheers, Lars

On Apr 15, 7:20 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
> If you can't establish the event at class declaration time, then the 
> @event.listens_for/event.listen() paradigm 
> (seehttp://docs.sqlalchemy.org/en/latest/core/event.htmlfor background) can 
> be applied to the class-bound attribute (which here is "Positive.value") at 
> any time.  "Positive.value" is an attribute generated by the mapping which is 
> a result of using the declarative base.
>
> On Apr 15, 2012, at 1:10 PM, lars van gemerden wrote:
>
>
>
>
>
>
>
> > OK, this helps, so how do i do this if i do not know the name of the
> > attribute to be checked  in advance(the "value" in
> > @validates("value") )?
>
> > On Apr 15, 6:52 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
> >> using type() is equivalent to using a class declaration.   The end result 
> >> is the same, as are the mechanics of what goes on both from a Python as 
> >> well as a SQLAlchemy perspective.  So this works:
>
> >> Positive = type("Positive", (Base,), dict(__tablename__ =
> >> "positives",  value = Column(Integer)))
>
> >> @event.listens_for(Positive.value, "set")
> >> def checkvalue(target, value, oldvalue, initiator)
> >>    assert value > 0
>
> >> and also, since type() is equivalent to a class declaration, you can still 
> >> use @validates,  if you pass the function into the class dictionary, so 
> >> that it is part of the class before declarative sends it off to mapper():
>
> >> @validates("value")
> >> def checkvalue(self, name, value):
> >>     assert value > 0
> >>     return value
>
> >> Positive = type("Positive", (Base,), dict(__tablename__ =
> >> "positives",  value = Column(Integer), checkvalue=checkvalue))
>
> >> On Apr 15, 2012, at 12:37 PM, lars van gemerden wrote:
>
> >>> I don't know what "@validates hangs a marker of the method that
> >>> mapper() uses when it instruments the class" means. I guess my
> >>> question now becomes: How do I add the event.listens_for descriptor to
> >>> the class, since i do not have a class declaration in the traditional
> >>> sense?
>
> >>> On Apr 15, 4:29 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
> >>>> @validates hangs a marker of the method that mapper() uses when it 
> >>>> instruments the class, so if the class is already mapped then that train 
> >>>> has left the station.   Taking a cab instead, you can just add the 
> >>>> attribute event directly:
>
> >>>> @event.listens_for(Positive.value, "set")
> >>>> def checkvalue(target, value, oldvalue, initiator)
> >>>>    assert value > 0
>
> >>>> if you want to return a new, mutated value then add retval=True to 
> >>>> listens_for().
>
> >>>> On Apr 15, 2012, at 8:22 AM, lars van gemerden wrote:
>
> >>>>> Hi,
>
> >>>>> I need a way to dynamically add a validates method to a already
> >>>>> created sqla class.
>
> >>>>> In a normal class declaration you can add a validator by:
>
> >>>>> class Positive(Base):
> >>>>>    __tablename__ = "positives"
> >>>>>    value = Column(Integer)
>
> >>>>>    def checkvalue(self, name, value):
> >>>>>        assert value > 0
> >>>>>        return value
> >>>>>    validates("value")(checkvalue)
>
> >>>>> However if you get the class dynamically:
>
> >>>>> Positive = type("Positive", (Base,), dict(__tablename__ =
> >>>>> "positives",  value = Column(Integer)))
>
> >>>>> I can't figure out how to add the validator, either in the type() call
> >>>>> or afterwards.
>
> >>>>> Cheers, Lars
>
> >>>>> --
> >>>>> You received this message because you are subscribed to the Google 
> >>>>> Groups "sqlalchemy" group.
> >>>>> To post to this group, send email to sqlalchemy@googlegroups.com.
> >>>>> To unsubscribe from this group, send email to 
> >>>>> sqlalchemy+unsubscr...@googlegroups.com.
> >>>>> For more options, visit this group 
> >>>>> athttp://groups.google.com/group/sqlalchemy?hl=en.
>
> >>> --
> >>> You received this message because you are subscribed to the Google Groups 
> >>> "sqlalchemy" group.
> >>> To post to this group, send email to sqlalchemy@googlegroups.com.
> >>> To unsubscribe from this group, send email to 
> >>> sqlalchemy+unsubscr...@googlegroups.com.
> >>> For more options, visit this group 
> >>> athttp://groups.google.com/group/sqlalchemy?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "sqlalchemy" group.
> > To post to this group, send email to sqlalchemy@googlegroups.com.
> > To unsubscribe from this group, send email to 
> > sqlalchemy+unsubscr...@googlegroups.com.
> > For more options, visit this group 
> > athttp://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to