Section 17.6. Error and Exception Handling


17.6. Error and Exception Handling

TurboGears maintains separate mechanisms for handling data validation errors and program exceptions. We start by covering errors and move on to exceptions.

17.6.1. Validation Errors

Every method decorated by validate() requires a corresponding error handler. The most straightforward way to do so is to declare a function an error handler for a given method via the error_handler() decorator:

@validate(form=my_form) @error_handler(my_eh) def register(self, name=None, age=None, email=None):


The function declared as an error handler can have an arbitrary signature, but you might want to declare a parameter tg_errors wherein a mapping of argument names to errors will be passed. If the same error handler is used for multiple methods, an argument tg_source mapped to the method that triggered the error can prove useful.

Other parameters of interest are any named the same as arguments being validated, allowing us to fully reconstruct the original call. Although not strictly necessary, it is considered good practice to provide default values for any such arguments:

def my_eh(self, tg_errors, tg_source, name=None, email=None):


A more general approach is to use *identifier and **identifier.

Of course, nothing prevents us from using an existing (exposed) method as an error handler.

A method can even be its own error handler when error_handler is applied without any arguments:

@error_handler()


Take care with this approach because it can introduce subtle bugs. In general, the order of your decorators doesn't matter, but error_handler changes program flow, so it can bypass other decorators. For the most part, this causes no problem because it's exactly what you want. But, if you place your error_handler decorator below identity_require, you're authorization check won't be performed when there's an error.

@validate(validators={"num":validators.Int(),                       "content":validators.NotEmpty()}) @identity.require(in_group("editor")) @error_handler() def page(self, num, content=None):


You can be careful to always put error_handler above identity_require, oralternativelyyou can declare the parameter tg_errors in the method itself like this:

def page(self, num, content=None, tg_errors=None):


Be aware that tg_errors should be a keyword argument when used in this manner (because for valid input, the method will not get re-called as error handler, and therefore tg_errors will not get passed in).

If no applicable error handler is defined and validation fails, NotImplementedError exception (from the standard library) is raised.

17.6.2. Multiple Handlers

What if we want to handle certain validation errors differently than the rest? Fortunately, more than one error_handler() can be applied to a method. In such a scenario, the appropriate error handler is selected based on an arbitrary Python logical expression passed as a string via keyword argument rules. (Careful readers will note this is not unlike expose(); in fact, error_handler() is just an interface to an underlying generic function.)

@error_handler(pagenum_eh, "'num' in tg_errors") @error_handler(content_eh)


The most specific applicable rule is selected, meaning if validation of num fails, pagenum_eh will be called regardless of the content's state; or in other words, content_eh will be called if and only if validation of content fails and num passes.

Because both arguments of error_handler are optional, specialization is possible even when the method is its own error handler:

@error_handler(rules="'num' in tg_errors")


(Recall that if the first argument is omitted, the method is declared its own error handler.)

17.6.3. Exception Handling

Analogous to error_handler() and tg_errors, TurboGears provides exception_handler() and tg_exceptions for handling program exceptions.

When no applicable exception handler is defined, the exception is passed to a lower layer (for example, CherryPy).

If having the same handler for both errors and exceptions is desired, you can use errorhandling.register_handler, which is similar to error_handler and exception_handler but without inherent specializations.




Rapid Web Applications with TurboGears(c) Using Python to Create Ajax-Powered Sites
Rapid Web Applications with TurboGears: Using Python to Create Ajax-Powered Sites
ISBN: 0132433885
EAN: 2147483647
Year: 2006
Pages: 202

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net