Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 18 and Version 19 of HowDoesErrorHandlingWork


Ignore:
Timestamp:
03/04/08 19:20:39 (11 years ago)
Author:
Chris Arndt
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • HowDoesErrorHandlingWork

    v18 v19  
    1 = How does error handling work = 
     1{{{ 
    22 
    3 '''WARNING: error handling is still in state of flux, the following page is primarily intended for developers.''' 
     3#!rst 
    44 
    5 = 1 Validation errors = 
    6  
    7 Definitions: 
    8  
    9   '''error handler''' -- method called when an error occurs. 
    10  
    11 Let foo be a function defined as 
    12 {{{ 
    13 @expose() 
    14 @validate(validators={"bar":validators.Int()}, "baz":validators.Int()) 
    15 def foo(self, bar=None, baz=None): 
    16     pass 
    17 }}} 
    18 == 1.1 Basics == 
    19  
    20 Basic form of error handling is via decorator ''error_handler'' with error handler as argument: 
    21 {{{ 
    22 @error_handler(my_eh) 
    23 }}} 
    24 my_eh can have an arbitrary signature, however one might wish to declare parameter ''tg_errors'' wherein errors (causing our error handler to be called) will be passed. 
    25 Other parameters of interest are any named the same as arguments being validated, allowing us to fully reconstruct the original call (that failed validation). 
    26 A more general approach would be using ''*identifier'' and ''**identifier''. 
    27  
    28 my_eh now looks something like: 
    29 {{{ 
    30 def my_eh(self, tg_errors, bar): 
    31     pass 
     5.. note:: This page has been migrated to http://docs.turbogears.org/1.0/HowDoesErrorHandlingWork 
    326}}} 
    337 
    34 Of curse nothing prevents us from using an existing (exposed) method as error handler. 
    35  
    36 A method can even be it's own error handler when ''error_handler'' is applied without any arguments: 
    37 {{{ 
    38 @error_handler() 
    39 }}} 
    40 Care should be taken with this approach as it can introduce subtle bugs. Consider the following example: 
    41 {{{ 
    42 @expose() 
    43 @validate(...) 
    44 @identity.require(...) 
    45 @error_handler() 
    46 def foo(self, bar=None, baz=None): 
    47 }}} 
    48 Whenever validation fails '''''identity.require'' will be by-passed'''! This happens because the function '''as it was at decoration time''' is registered as error handler.  
    49  
    50 A safer alternative is to for the method do declare parameter tg_errors: 
    51 {{{ 
    52 def foo(self, bar=None, tg_errors=None): 
    53 }}} 
    54  
    55 Mind, ''tg_errors'' should be a keyword argument, when used in this manner (since for valid input the method will not get re-called as error handler, hence ''tg_errors'' will not get passed in). 
    56  
    57 If no appropriate error handler is defined and validation failed, ''NotImplementedError'' exception (from standard library) is raised. 
    58  
    59 == 1.2 Dispatch rules == 
    60  
    61 What if we want to handle invalid baz-es differently than invalid bar-s? Fortunately for us, ''error_handler'' takes a second keyword argument ''rules'', making it possible to influence selection of appropriate error handler (actually a limited interface to ''RuleDispatch''[1]). 
    62 Rules are arbitrary logical Python expressions passed as strings. For example: 
    63 {{{ 
    64 @error_handler(baz_eh, "'baz' in tg_errors") 
    65 @error_handler(bar_eh) 
    66 }}} 
    67 The most specific applicable rule is selected, meaning if validation of baz fails, baz_eh will be called regardless of bar's state or in other words, bar_eh will be called if and only if validation of bar fails and baz passes. 
    68  
    69 Any number of calls to ''error_handler'' can be made with the same handler. 
    70  
    71 Since both arguments of ''error_handler'' are optional, specialisation is possible even when method is it's own error handler: 
    72 {{{ 
    73 @error_handler(rules="'baz' in tg_errors") 
    74 }}} 
    75  
    76  
    77 == 1.3 Fail-safe mechanism == 
    78  
    79 If validation fails for an input, said input also does not get to be converted to designated Python type, which could be rather inconvenient. A fail-safe mechanism is provided for such cases.  
    80  
    81 = 2 Exceptions = 
    82  
    83  
    84 == 2.1 Basics == 
    85  
    86 Analogue to ''error_handler'' and ''tg_errors'', ''exception_handler'' and ''tg_exceptions'' are defined. 
    87  
    88 If no appropriate exception handler is defined, exception is passed to a lower layer (e.g. CherryPy). 
    89  
    90 == 2.2 Combining with error handling == 
    91  
    92 One method can have any number of exception handlers and error handlers. 
    93  
    94 If having the same handler for errors and exceptions is desired, one can use ''errorhandling.register_handler'' which is similar to ''error_handler'' and ''exception_handler'' but without inherent specialisations. 
    95  
    96  
    97 = 3 Advanced topics = 
    98  
    99 == 3.1 Utilities == 
    100  
    101 === 3.1.1 bind_args === 
    102  
    103 === 3.1.2 bind_rules === 
    104  
    105 == 3.2 Generic functions == 
    106  
    107 == 3.3 Continuations == 
    108  
    109  
    110 ---- 
    111  
    112 == References == 
    113  
    114 [1] http://www-128.ibm.com/developerworks/library/l-cppeak2/index.html 
    115  
    116 == Further reading == 
    117  
    118 === Source === 
    119  
    120 source:trunk/turbogears/errorhandling.py 
    121  
    122 source:trunk/turbogears/tests/test_errorhandling.py 
    123  
    124 === Generic functions === 
    125  
    126 http://peak.telecommunity.com/PyCon05Talk/ 
    127  
    128 http://peak.telecommunity.com/DevCenter/CombiningResults 
    129  
    130 http://peak.telecommunity.com/DevCenter/VisitorRevisited 
    131  
    132 http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html 
    133  
    134 === Continuations === 
    135  
    136 http://www.ps.uni-sb.de/~duchier/python/continuations.html