Full error handling
[invirt/packages/invirt-web.git] / code / view.py
index d15d53f..6c9caf8 100644 (file)
@@ -1,10 +1,11 @@
-import os
+import os, sys
 
 import cherrypy
 from mako.template import Template
 from mako.lookup import TemplateLookup
 import simplejson
 import datetime, decimal
 
 import cherrypy
 from mako.template import Template
 from mako.lookup import TemplateLookup
 import simplejson
 import datetime, decimal
+from StringIO import StringIO
 from invirt.config import structs as config
 from webcommon import State
 
 from invirt.config import structs as config
 from webcommon import State
 
@@ -27,10 +28,9 @@ class MakoLoader(object):
     
     def __init__(self):
         self.lookups = {}
     
     def __init__(self):
         self.lookups = {}
-    
-    def __call__(self, filename, directories, module_directory=None,
-                 collection_size=-1, content_type='text/html; charset=utf-8',
-                 imports=[]):
+
+    def get_lookup(self, directories, module_directory=None,
+                     collection_size=-1, imports=[], **kwargs):
         # Find the appropriate template lookup.
         key = (tuple(directories), module_directory)
         try:
         # Find the appropriate template lookup.
         key = (tuple(directories), module_directory)
         try:
@@ -45,7 +45,13 @@ class MakoLoader(object):
                                     imports=imports,
                                     )
             self.lookups[key] = lookup
                                     imports=imports,
                                     )
             self.lookups[key] = lookup
-        cherrypy.request.lookup = lookup
+        return lookup
+
+    def __call__(self, filename, directories, module_directory=None,
+                 collection_size=-1, content_type='text/html; charset=utf-8',
+                 imports=[]):
+        cherrypy.request.lookup = lookup = self.get_lookup(directories, module_directory,
+                                                           collection_size, imports)
         
         # Replace the current handler.
         cherrypy.request.template = t = lookup.get_template(filename)
         
         # Replace the current handler.
         cherrypy.request.template = t = lookup.get_template(filename)
@@ -54,6 +60,30 @@ class MakoLoader(object):
 main = MakoLoader()
 cherrypy.tools.mako = cherrypy.Tool('on_start_resource', main)
 
 main = MakoLoader()
 cherrypy.tools.mako = cherrypy.Tool('on_start_resource', main)
 
+def revertStandardError():
+    """Move stderr to stdout, and return the contents of the old stderr."""
+    errio = sys.stderr
+    if not isinstance(errio, StringIO):
+        return ''
+    sys.stderr = sys.stdout
+    errio.seek(0)
+    return errio.read()
+
+def catchStderr():
+    old_handler = cherrypy.request.handler
+    def wrapper(*args, **kwargs):
+        sys.stderr = StringIO()
+        ret = old_handler(*args, **kwargs)
+        e = revertStandardError()
+        if e:
+            if isinstance(ret, dict):
+                ret["error_text"] = e
+        return ret
+    if old_handler:
+        cherrypy.request.handler = wrapper
+
+cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
+
 class JSONEncoder(simplejson.JSONEncoder):
        def default(self, obj):
                if isinstance(obj, datetime.datetime):
 class JSONEncoder(simplejson.JSONEncoder):
        def default(self, obj):
                if isinstance(obj, datetime.datetime):