[sqlalchemy] Re: dynamically adding a validates method
PS: the validate(value) method in typedef[name] is a normal method, throwing exception on errors and returning the value when OK. On Apr 16, 2:01 pm, lars van gemerden wrote: > 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 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.htmlforbackground) 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 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 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 "sqla
[sqlalchemy] Re: dynamically adding a validates method
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 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 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 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 G
Re: [sqlalchemy] Re: dynamically adding a validates method
If you can't establish the event at class declaration time, then the @event.listens_for/event.listen() paradigm (see http://docs.sqlalchemy.org/en/latest/core/event.html for 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 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 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 at > http://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.
[sqlalchemy] Re: dynamically adding a validates method
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 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 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 at http://groups.google.com/group/sqlalchemy?hl=en.
Re: [sqlalchemy] Re: dynamically adding a validates method
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 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 at > http://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.
[sqlalchemy] Re: dynamically adding a validates method
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 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 at http://groups.google.com/group/sqlalchemy?hl=en.