summaryrefslogtreecommitdiff
path: root/paste/evalexception
diff options
context:
space:
mode:
authorianb <devnull@localhost>2006-02-21 01:09:30 +0000
committerianb <devnull@localhost>2006-02-21 01:09:30 +0000
commit2d84d13c4ae91a081d6b2dfaf6ac9e9e53ee72ba (patch)
treeef729920d0693b6bfc321a74ca2c01adf42df1e0 /paste/evalexception
parentf6fb5e8087394ebca58239111391b3340bfb6317 (diff)
downloadpaste-2d84d13c4ae91a081d6b2dfaf6ac9e9e53ee72ba.tar.gz
Refactored so each traceback has its own URL, that will be printed to wsgi.errors, and you can visit it there even if it was in response to an Ajax call. Also X-Debug-URL is sent with the URL for the full traceback
Diffstat (limited to 'paste/evalexception')
-rw-r--r--paste/evalexception/middleware.py89
1 files changed, 61 insertions, 28 deletions
diff --git a/paste/evalexception/middleware.py b/paste/evalexception/middleware.py
index f3b4c7a..df0d302 100644
--- a/paste/evalexception/middleware.py
+++ b/paste/evalexception/middleware.py
@@ -14,6 +14,13 @@ environments both work.
This shouldn't be used in production in any way. That would just be
silly.
+
+If calling from an XMLHttpRequest call, if the GET variable ``_`` is
+given then it will make the response more compact (and less
+Javascripty), since if you use innerHTML it'll kill your browser. You
+can look for the header X-Debug-URL in your 500 responses if you want
+to see the full debuggable traceback. Also, this URL is printed to
+``wsgi.errors``, so you can open it up in another browser window.
"""
import sys
import os
@@ -190,6 +197,15 @@ class EvalException(object):
return app(environ, start_response)
mochikit.exposed = True
+ def view(self, environ, start_response):
+ id = int(wsgilib.path_info_pop(environ))
+ debug_info = self.debug_infos[id]
+ return debug_info.wsgi_application(environ, start_response)
+ view.exposed = True
+
+ def make_view_url(self, environ, base_path, count):
+ return base_path + '/_debug/view/%s' % count
+
#@wsgiapp()
#@get_debug_info
def show_frame(self, tbid, debug_info, **kw):
@@ -225,7 +241,8 @@ class EvalException(object):
def respond(self, environ, start_response):
if environ.get('paste.throw_errors'):
return self.application(environ, start_response)
- base_path = environ['SCRIPT_NAME']
+ base_path = request.construct_url(environ, with_path_info=False,
+ with_query_string=False)
environ['paste.throw_errors'] = True
started = []
def detect_start_response(status, headers, exc_info=None):
@@ -250,10 +267,15 @@ class EvalException(object):
if issubclass(exc_info[0], expected):
raise
+ count = debug_counter.next()
+ view_uri = self.make_view_url(environ, base_path, count)
if not started:
+ headers = [('content-type', 'text/html')]
+ headers.append(('X-Debug-URL', view_uri))
start_response('500 Internal Server Error',
- [('content-type', 'text/html')],
+ headers,
exc_info)
+ environ['wsgi.errors'].write('Debug at: %s\n' % view_uri)
if self.xmlhttp_key:
get_vars = wsgilib.parse_querystring(environ)
@@ -264,21 +286,13 @@ class EvalException(object):
include_reusable=False, show_extra_data=False)
return [html]
- count = debug_counter.next()
- debug_info = DebugInfo(count, exc_info)
+ exc_data = collector.collect_exception(*exc_info)
+ debug_info = DebugInfo(count, exc_info, exc_data, base_path,
+ environ)
assert count not in self.debug_infos
self.debug_infos[count] = debug_info
# @@: it would be nice to deal with bad content types here
- exc_data = collector.collect_exception(*exc_info)
- html = format_eval_html(exc_data, base_path, count)
- head_html = (formatter.error_css + formatter.hide_display_js)
- head_html += self.eval_javascript(base_path, count)
- repost_button = make_repost_button(environ)
- page = error_template % {
- 'repost_button': repost_button or '',
- 'head_html': head_html,
- 'body': html}
- return [page]
+ return debug_info.content()
def catching_iter(self, app_iter, environ):
__traceback_supplement__ = errormiddleware.Supplement, self, environ
@@ -316,23 +330,14 @@ class EvalException(object):
debug_mode=True,
simple_html_error=simple_html_error)
- def eval_javascript(self, base_path, counter):
- base_path += '/_debug'
- return (
- '<script type="text/javascript" src="%s/mochikit/MochiKit.js">'
- '</script>\n'
- '<script type="text/javascript" src="%s/media/debug.js">'
- '</script>\n'
- '<script type="text/javascript">\n'
- 'debug_base = %r;\n'
- 'debug_count = %r;\n'
- '</script>\n'
- % (base_path, base_path, base_path, counter))
-
class DebugInfo(object):
- def __init__(self, counter, exc_info):
+ def __init__(self, counter, exc_info, exc_data, base_path,
+ environ):
self.counter = counter
+ self.exc_data = exc_data
+ self.base_path = base_path
+ self.environ = environ
self.exc_type, self.exc_value, self.tb = exc_info
__exception_formatter__ = 1
self.frames = []
@@ -354,6 +359,34 @@ class DebugInfo(object):
raise ValueError, (
"No frame by id %s found from %r" % (tbid, self.frames))
+ def wsgi_application(self, environ, start_response):
+ start_response('200 OK', [('content-type', 'text-html')])
+ return self.content()
+
+ def content(self):
+ html = format_eval_html(self.exc_data, self.base_path, self.counter)
+ head_html = (formatter.error_css + formatter.hide_display_js)
+ head_html += self.eval_javascript()
+ repost_button = make_repost_button(self.environ)
+ page = error_template % {
+ 'repost_button': repost_button or '',
+ 'head_html': head_html,
+ 'body': html}
+ return [page]
+
+ def eval_javascript(self):
+ base_path = self.base_path + '/_debug'
+ return (
+ '<script type="text/javascript" src="%s/mochikit/MochiKit.js">'
+ '</script>\n'
+ '<script type="text/javascript" src="%s/media/debug.js">'
+ '</script>\n'
+ '<script type="text/javascript">\n'
+ 'debug_base = %r;\n'
+ 'debug_count = %r;\n'
+ '</script>\n'
+ % (base_path, base_path, base_path, self.counter))
+
class EvalHTMLFormatter(formatter.HTMLFormatter):
def __init__(self, base_path, counter, **kw):