--- c:\TurboGears\turbogears\turbogears\controllers.py	2006-01-12 12:56:03.296875000 +0100
+++ C:\Documents and Settings\Simon\My Documents\hruska\TurboGears\controllers.py	2006-01-12 12:53:46.125000000 +0100
@@ -8,6 +8,7 @@
 import kid
 import formencode
 import warnings
+from dispatch import generic, strategy
 
 import view
 from turbogears.util import setlike
@@ -140,9 +141,12 @@
         rather than defining a validation_error method.""")
                     output = self.validation_error(func.func_name, kw, errors)
                 else:
-                    output = _call_with_errors(func, self, *args, **kw)
+                    output = _dispatch_error(func, self, errors, *args, **kw)
             else:
-                output = func(self, *args, **kw)
+                try:
+                    output = func(self, *args, **kw)
+                except Exception, errors:
+                    output = _dispatch_error(func, self, errors, *args, **kw)
             return output
         try:
             newfunc.func_name = func.func_name
@@ -285,6 +289,48 @@
         message = None
     return message
 
+
+def _dispatch_error(error_source, self, errors, *args, **kw):
+    """ Dispatch error.
+
+    Error handler is a function registered via error_handler decorator or
+    the method that triggered the error (hence forth referred to as
+    "old-style").
+    """
+_dispatch_error = generic()(_dispatch_error)
+
+def _oldstyle_error_handling(error_source, self, errors, *args, **kw):
+    """ Dispatch error old-style like. """
+    return _call_with_errors(error_source, self, *args, **kw)
+_oldstyle_error_handling = _dispatch_error.when(strategy.default)(
+                           _oldstyle_error_handling)
+
+def error_handler(handler, dispatch_rules=None):
+    """ Register handler as an error handler for func.
+
+    dispatch_rules can be a string containing an arbitrary logical Python
+    expression to be used as dispatch rule allowing multiple error handlers
+    for a single method.
+
+    error_handler decorator is an invariant.
+    """
+    def register(func):
+        when = "error_source.__name__ == '%s'" % func.__name__
+        if dispatch_rules:
+            when += " and (%s)" % dispatch_rules
+
+        # First argument of _dispatch_error is only used in dispatch rules,
+        # therefore application code need not declare it.
+        def normalize(func):
+            def prepend_arg(error_source, self, errors, *args, **kw):
+                return func(self, errors, *args, **kw)
+            return prepend_arg
+
+        _dispatch_error.when(when)(normalize(handler))
+        return func
+    return register
+
+
 class Controller(cherrypy.lib.cptools.PositionalParametersAware):
     """Base class for a web application's controller.
 
@@ -306,5 +352,5 @@
             turbogears.url(tgpath=redirect_path,
                            tgparams=redirect_params, **kw))
 
-__all__ = ["expose", "validate", "redirect",
+__all__ = ["expose", "validate", "redirect", "error_handler",
             "flash", "Root", "RootController", "Controller"]
