[TurboGears] Re: How does the current validator mechanism works ?
Kevin Dangoor wrote: Validation errors should be genuine errors. If it's valid for a value to be empty, the validators should be configured that way... Even so, it should usually be handled by the function that knows about it, not some catch all. In fact, I have a mix feeling about the liberal use of exception in python. Some how, it no longer seems like exception to me but random go tos. getattr(self, methodname)(params) This won't work if it is defined like this : @turbogears.expose() @my_decorator() def foo(self): What turogears see is my_decorator, not foo but validate_error see self which tries to search for my_decorator and won't find it as it could be some function in outer space.
[TurboGears] Re: How does the current validator mechanism works ?
[EMAIL PROTECTED] wrote: This won't work if it is defined like this : @turbogears.expose() @my_decorator() def foo(self): What turogears see is my_decorator, not foo but validate_error see self which tries to search for my_decorator and won't find it as it could be some function in outer space. There's a decorator library out there (somewhere, can't find it now) that fixes up things like the function name, so @my_decorator (if it used that library) could wrap foo, and the wrapper function will also appear to be named foo. -- Ian Bicking / [EMAIL PROTECTED] / http://blog.ianbicking.org
[TurboGears] Re: How does the current validator mechanism works ?
thanks. But that sounds like twisting my arm in the back for 720 degree in order to fit what it is now. Which is also why I start this topic, what is the rationale for the current design. I could have missed some significant advantage of why it is design this way. Ian Bicking wrote: [EMAIL PROTECTED] wrote: This won't work if it is defined like this : @turbogears.expose() @my_decorator() def foo(self): What turogears see is my_decorator, not foo but validate_error see self which tries to search for my_decorator and won't find it as it could be some function in outer space. There's a decorator library out there (somewhere, can't find it now) that fixes up things like the function name, so @my_decorator (if it used that library) could wrap foo, and the wrapper function will also appear to be named foo. -- Ian Bicking / [EMAIL PROTECTED] / http://blog.ianbicking.org
[TurboGears] Re: How does the current validator mechanism works ?
I agree completely. In my project my validation_error method has to do just that: recall the original method with all arguments + and errors argument. This seems the best approach and the code is fairly boiler plate. It would be nice to see this as the default behaviour in TG. Krys [EMAIL PROTECTED] wrote: I begin to start using the validator and got confused of what is the design philosophy behind it. 1. There is an instance method validator_error that would be called if exist otherwise it would raise another exception. I believe this has to be mentioned in the documentation as otherwise, this exception would not be caught by anyone and it would be the ugly server get in trouble message, which is very scary but not the case. Just some data content error. If validator_error is defined, if will be called with the first parameter being the original function(the one that turbogears.expose supposed to be decorating). While the documentation said I can do whatever I want, I think it would be more natural to let the original function deal with it as this validator_error is a centralized function(sort of catch all) that is impossible to make meaningful error message/response. Would it be better to just have a convention that any exposed function that has validator enabled should expect one more argument error=None to indicate such condition and let it do its job there ?
[TurboGears] Re: How does the current validator mechanism works ?
What about a nested validation_error function. For example: @turbogears.expose( validators= mySchema() ) def index( self, arg1, arg2 ) def validation_failed( errors ): # do something clever here and ultimately # either retry index or bail pass # real code for index pass Is it legal to have a self parameter for the nested function? If so, I guess we'll have to pass it along explicitly when calling the nested validation_failed function. Of course, if no validation_failed function is defined, the class- based one should be tried next. -- Jeff Watkins http://metrocat.org/ Advertising directed at children is inherently deceptive and exploits children under eight years of age. -- American Academy of Pediatrics
[TurboGears] Re: How does the current validator mechanism works ?
Ian Bicking wrote: [EMAIL PROTECTED] wrote: [snip] If validator_error is defined, if will be called with the first parameter being the original function(the one that turbogears.expose supposed to be decorating). While the documentation said I can do whatever I want, I think it would be more natural to let the original function deal with it as this validator_error is a centralized function(sort of catch all) that is impossible to make meaningful error message/response. It seems to me that another function should be called, but one that is a sister function, not a single validation_error function. A particularly common one would be the function that originally generated the form, so it could regenerate the form with the errors in it. So it might be: @expose(validators=..., on_error='register'): def do_registration(self, ...): # actually perform action @expose(html='form.html'): def register(self): # creates form with action=do_registration # maybe expose pipes the output through htmlfill if this # is in response to an error, or... something This works much better than a generic validation_error method, IMHO. Whether the same method is used to display the form and process the form data or not should be up to the programmer, but coding is much simpler if I can just say ok, were there any errors, rather than from which method did I get these errors and how to I tell it that there were errors. Krys
[TurboGears] Re: How does the current validator mechanism works ?
Exactly. Validation errors are not usually programming errors. They are usually user input errors. Telling the user that they have inputted invalid data should be simple and intuitive. A separate method for error handling is not intuitive to me. :-) Krys [EMAIL PROTECTED] wrote: To me it seems like it should be an error if there's no validation_error method and any validators are given. This way the error is caught early during development. Yes, but there are sometimes(many times I would say) soft-errors that don't need this kind of handling. A typical case would be the fields may come in as nothing(None) which can be a don't care and proceed. defining validation_error would grab the control of it without giving it a chance to go on. And I re-read the code, what validation_error received is not the original function, but the name of the function, making calling it back a bit difficult.
[TurboGears] Re: How does the current validator mechanism works ?
Interesting idea. :-) I am unsure what benefit it provides over just say just having an extra errors=None argument on the original method. I'd love to hear your thoughts on it though. :-) It seems to me that that there are two simple ways of handling validation errors: 1) Adding an errors=None argument to the method and letting it handle things (so the validators would just populate the errors dict and pass them on to the method), or 2) Ian's idea of an on_error='method_name' added to expose. Actually, now that I am thinking of it, I'd say combine the two ideas. If no on_error is provided assume the on_error method is the method being decorated, otherwise call the specified method. Whatever method is called would have and errors keyword argument which is a dictionary in the form of: {'form_field_name': [list of Invalid objects],...} That way you can have, as Ian believes, separate methods for presentation of a form and processing of it, or you can have one method responsible for both, as others prefer. In either case, the method that knows best about it's subject matter is responsible for handling the errors, instead of some generic validation_error method that knows nothing of the specifics of the original method that was called. Anyway, just my $.02. Shoot me down if out in left field. :-) Krys Jeff Watkins wrote: What about a nested validation_error function. For example: @turbogears.expose( validators= mySchema() ) def index( self, arg1, arg2 ) def validation_failed( errors ): # do something clever here and ultimately # either retry index or bail pass # real code for index pass Is it legal to have a self parameter for the nested function? If so, I guess we'll have to pass it along explicitly when calling the nested validation_failed function. Of course, if no validation_failed function is defined, the class- based one should be tried next. -- Jeff Watkins http://metrocat.org/ Advertising directed at children is inherently deceptive and exploits children under eight years of age. -- American Academy of Pediatrics
[TurboGears] Re: How does the current validator mechanism works ?
Agree. In its(TurboGears) current form, I have changed all my functions to this form(thus ignore the validator feature) : func(self,**kwargs): Then I can define a formencode schema to validate against kwargs which is a dict. Basically achieve what you mentioned. The only issue is, a few line of code is needed to grab the keywords that is needed for processing, back from kwargs, rather than func(self, something=None,someother=None). But kwargs is needed anyway(as the kitchen sink) or any strange hidden fields in a form would bomb. Krys Wilken wrote: Interesting idea. :-) I am unsure what benefit it provides over just say just having an extra errors=None argument on the original method. I'd love to hear your thoughts on it though. :-) It seems to me that that there are two simple ways of handling validation errors: 1) Adding an errors=None argument to the method and letting it handle things (so the validators would just populate the errors dict and pass them on to the method), or 2) Ian's idea of an on_error='method_name' added to expose. Actually, now that I am thinking of it, I'd say combine the two ideas. If no on_error is provided assume the on_error method is the method being decorated, otherwise call the specified method. Whatever method is called would have and errors keyword argument which is a dictionary in the form of: {'form_field_name': [list of Invalid objects],...} That way you can have, as Ian believes, separate methods for presentation of a form and processing of it, or you can have one method responsible for both, as others prefer. In either case, the method that knows best about it's subject matter is responsible for handling the errors, instead of some generic validation_error method that knows nothing of the specifics of the original method that was called. Anyway, just my $.02. Shoot me down if out in left field. :-) Krys Jeff Watkins wrote: What about a nested validation_error function. For example: @turbogears.expose( validators= mySchema() ) def index( self, arg1, arg2 ) def validation_failed( errors ): # do something clever here and ultimately # either retry index or bail pass # real code for index pass Is it legal to have a self parameter for the nested function? If so, I guess we'll have to pass it along explicitly when calling the nested validation_failed function. Of course, if no validation_failed function is defined, the class- based one should be tried next. -- Jeff Watkins http://metrocat.org/ Advertising directed at children is inherently deceptive and exploits children under eight years of age. -- American Academy of Pediatrics
[TurboGears] Re: How does the current validator mechanism works ?
To me it seems like it should be an error if there's no validation_error method and any validators are given. This way the error is caught early during development. Yes, but there are sometimes(many times I would say) soft-errors that don't need this kind of handling. A typical case would be the fields may come in as nothing(None) which can be a don't care and proceed. defining validation_error would grab the control of it without giving it a chance to go on. And I re-read the code, what validation_error received is not the original function, but the name of the function, making calling it back a bit difficult.
[TurboGears] Re: How does the current validator mechanism works ?
[EMAIL PROTECTED] wrote: I begin to start using the validator and got confused of what is the design philosophy behind it. 1. There is an instance method validator_error that would be called if exist otherwise it would raise another exception. I believe this has to be mentioned in the documentation as otherwise, this exception would not be caught by anyone and it would be the ugly server get in trouble message, which is very scary but not the case. Just some data content error. To me it seems like it should be an error if there's no validation_error method and any validators are given. This way the error is caught early during development. If validator_error is defined, if will be called with the first parameter being the original function(the one that turbogears.expose supposed to be decorating). While the documentation said I can do whatever I want, I think it would be more natural to let the original function deal with it as this validator_error is a centralized function(sort of catch all) that is impossible to make meaningful error message/response. It seems to me that another function should be called, but one that is a sister function, not a single validation_error function. A particularly common one would be the function that originally generated the form, so it could regenerate the form with the errors in it. So it might be: @expose(validators=..., on_error='register'): def do_registration(self, ...): # actually perform action @expose(html='form.html'): def register(self): # creates form with action=do_registration # maybe expose pipes the output through htmlfill if this # is in response to an error, or... something -- Ian Bicking / [EMAIL PROTECTED] / http://blog.ianbicking.org