summaryrefslogtreecommitdiff
path: root/django/views/debug.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/views/debug.py')
-rw-r--r--django/views/debug.py69
1 files changed, 49 insertions, 20 deletions
diff --git a/django/views/debug.py b/django/views/debug.py
index 77b6c2fac2..75b1a26af9 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -2,7 +2,7 @@ from django.conf import settings
from django.template import Template, Context, TemplateDoesNotExist
from django.utils.html import escape
from django.http import HttpResponseServerError, HttpResponseNotFound
-import os, re
+import os, re, sys
HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST')
@@ -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)
frames = []
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
function = tb.tb_frame.f_code.co_name
lineno = tb.tb_lineno - 1
- pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7)
- if pre_context_lineno:
+ loader = tb.tb_frame.f_globals.get('__loader__')
+ 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({
'tb': tb,
'filename': filename,
@@ -124,11 +131,13 @@ def technical_500_response(request, exc_type, exc_value, tb):
'request': request,
'request_protocol': request.is_secure() and "https" or "http",
'settings': get_safe_settings(),
+ 'sys_executable' : sys.executable,
+ 'sys_version_info' : '%d.%d.%d' % sys.version_info[0:3],
'template_info': template_info,
'template_does_not_exist': template_does_not_exist,
'loader_debug_info': loader_debug_info,
})
- return HttpResponseServerError(t.render(c), mimetype='text/html')
+ return HttpResponseServerError(t.iter_render(c), mimetype='text/html')
def technical_404_response(request, exception):
"Create a technical 404 error response. The exception should be the Http404."
@@ -144,13 +153,14 @@ def technical_404_response(request, exception):
t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template')
c = Context({
'root_urlconf': settings.ROOT_URLCONF,
+ 'request_path': request.path[1:], # Trim leading slash
'urlpatterns': tried,
'reason': str(exception),
'request': request,
'request_protocol': request.is_secure() and "https" or "http",
'settings': get_safe_settings(),
})
- return HttpResponseNotFound(t.render(c), mimetype='text/html')
+ return HttpResponseNotFound(t.iter_render(c), mimetype='text/html')
def empty_urlconf(request):
"Create an empty URLconf 404 error response."
@@ -158,25 +168,36 @@ def empty_urlconf(request):
c = Context({
'project_name': settings.SETTINGS_MODULE.split('.')[0]
})
- return HttpResponseNotFound(t.render(c), mimetype='text/html')
+ return HttpResponseNotFound(t.iter_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 (pre_context_lineno, pre_context, context_line, post_context).
"""
- try:
- source = open(filename).readlines()
- lower_bound = max(0, lineno - context_lines)
- upper_bound = lineno + context_lines
+ source = None
+ if loader is not None:
+ source = loader.get_source(module_name).splitlines()
+ else:
+ try:
+ f = open(filename)
+ try:
+ source = f.readlines()
+ finally:
+ f.close()
+ except (OSError, IOError):
+ pass
+ if source is None:
+ return None, [], None, []
- 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]]
+ lower_bound = max(0, lineno - context_lines)
+ upper_bound = lineno + context_lines
- return lower_bound, pre_context, context_line, post_context
- except (OSError, IOError):
- return None, [], None, []
+ 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
@@ -313,7 +334,15 @@ TECHNICAL_500_TEMPLATE = """
</tr>
<tr>
<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>
+ <th>Python Executable:</th>
+ <td>{{ sys_executable|escape }}</td>
+ </tr>
+ <tr>
+ <th>Python Version:</th>
+ <td>{{ sys_version_info }}</td>
</tr>
</table>
</div>
@@ -360,7 +389,7 @@ TECHNICAL_500_TEMPLATE = """
<ul class="traceback">
{% for frame in frames %}
<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 %}
<div class="context" id="c{{ frame.id }}">
@@ -591,7 +620,7 @@ TECHNICAL_404_TEMPLATE = """
<li>{{ pattern|escape }}</li>
{% endfor %}
</ol>
- <p>The current URL, <code>{{ request.path|escape }}</code>, didn't match any of these.</p>
+ <p>The current URL, <code>{{ request_path|escape }}</code>, didn't match any of these.</p>
{% else %}
<p>{{ reason|escape }}</p>
{% endif %}