diff options
author | ianb <devnull@localhost> | 2006-02-21 01:09:30 +0000 |
---|---|---|
committer | ianb <devnull@localhost> | 2006-02-21 01:09:30 +0000 |
commit | 2d84d13c4ae91a081d6b2dfaf6ac9e9e53ee72ba (patch) | |
tree | ef729920d0693b6bfc321a74ca2c01adf42df1e0 /paste/evalexception | |
parent | f6fb5e8087394ebca58239111391b3340bfb6317 (diff) | |
download | paste-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.py | 89 |
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): |