Fixed #3734 -- Added support for import hooks to the debugging traceback

output. Also respect hidden traceback frames. Thanks to Armin Ronacher.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@5051 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-04-21 04:37:31 +00:00
parent c2b1986525
commit 43cd7bb110
2 changed files with 35 additions and 16 deletions

View File

@ -180,6 +180,7 @@ answer newbie questions, and generally made Django that much better:
Brian Ray <http://brianray.chipy.org/> Brian Ray <http://brianray.chipy.org/>
remco@diji.biz remco@diji.biz
rhettg@gmail.com rhettg@gmail.com
Armin Ronacher
Oliver Rutherfurd <http://rutherfurd.net/> Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/> Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
David Schein David Schein

View File

@ -90,11 +90,18 @@ def technical_500_response(request, exc_type, exc_value, tb):
exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type, exc_value, tb) exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type, exc_value, tb)
frames = [] frames = []
while tb is not None: while tb is not None:
# support for __traceback_hide__ which is used by a few libraries
# to hide internal frames.
if tb.tb_frame.f_locals.get('__traceback_hide__'):
tb = tb.tb_next
continue
filename = tb.tb_frame.f_code.co_filename filename = tb.tb_frame.f_code.co_filename
function = tb.tb_frame.f_code.co_name function = tb.tb_frame.f_code.co_name
lineno = tb.tb_lineno - 1 lineno = tb.tb_lineno - 1
pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7) loader = tb.tb_frame.f_globals.get('__loader__')
if pre_context_lineno: module_name = tb.tb_frame.f_globals.get('__name__')
pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7, loader, module_name)
if pre_context_lineno is not None:
frames.append({ frames.append({
'tb': tb, 'tb': tb,
'filename': filename, 'filename': filename,
@ -161,24 +168,35 @@ def empty_urlconf(request):
}) })
return HttpResponseNotFound(t.render(c), mimetype='text/html') return HttpResponseNotFound(t.render(c), mimetype='text/html')
def _get_lines_from_file(filename, lineno, context_lines): def _get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None):
""" """
Returns context_lines before and after lineno from file. Returns context_lines before and after lineno from file.
Returns (pre_context_lineno, pre_context, context_line, post_context). Returns (pre_context_lineno, pre_context, context_line, post_context).
""" """
try: source = None
source = open(filename).readlines() if loader is not None:
lower_bound = max(0, lineno - context_lines) source = loader.get_source(module_name).splitlines()
upper_bound = lineno + context_lines else:
try:
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]] f = open(filename)
context_line = source[lineno].strip('\n') try:
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]] source = f.readlines()
finally:
return lower_bound, pre_context, context_line, post_context f.close()
except (OSError, IOError): except (OSError, IOError):
pass
if source is None:
return None, [], None, [] return None, [], None, []
lower_bound = max(0, lineno - context_lines)
upper_bound = lineno + context_lines
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]]
context_line = source[lineno].strip('\n')
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]]
return lower_bound, pre_context, context_line, post_context
# #
# Templates are embedded in the file so that we know the error handler will # Templates are embedded in the file so that we know the error handler will
# always work even if the template loader is broken. # always work even if the template loader is broken.
@ -314,7 +332,7 @@ TECHNICAL_500_TEMPLATE = """
</tr> </tr>
<tr> <tr>
<th>Exception Location:</th> <th>Exception Location:</th>
<td>{{ lastframe.filename }} in {{ lastframe.function }}, line {{ lastframe.lineno }}</td> <td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -361,7 +379,7 @@ TECHNICAL_500_TEMPLATE = """
<ul class="traceback"> <ul class="traceback">
{% for frame in frames %} {% for frame in frames %}
<li class="frame"> <li class="frame">
<code>{{ frame.filename }}</code> in <code>{{ frame.function }}</code> <code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>
{% if frame.context_line %} {% if frame.context_line %}
<div class="context" id="c{{ frame.id }}"> <div class="context" id="c{{ frame.id }}">