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:
parent
c2b1986525
commit
43cd7bb110
1
AUTHORS
1
AUTHORS
|
@ -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
|
||||||
|
|
|
@ -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 }}">
|
||||||
|
|
Loading…
Reference in New Issue