66
35
Create a technical server error response. The last three arguments are
67
36
the values returned from sys.exc_info() and friends.
70
template_does_not_exist = False
71
loader_debug_info = None
72
if issubclass(exc_type, TemplateDoesNotExist):
73
from django.template.loader import template_source_loaders
74
template_does_not_exist = True
75
loader_debug_info = []
76
for loader in template_source_loaders:
38
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
39
html = reporter.get_traceback_html()
40
return HttpResponseServerError(html, mimetype='text/html')
42
class ExceptionReporter:
44
A class to organize and coordinate reporting on exceptions.
46
def __init__(self, request, exc_type, exc_value, tb):
47
self.request = request
48
self.exc_type = exc_type
49
self.exc_value = exc_value
52
self.template_info = None
53
self.template_does_not_exist = False
54
self.loader_debug_info = None
56
# Handle deprecated string exceptions
57
if isinstance(self.exc_type, basestring):
58
self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
59
self.exc_type = type(self.exc_value)
61
def get_traceback_html(self):
62
"Return HTML code for traceback."
64
if issubclass(self.exc_type, TemplateDoesNotExist):
65
from django.template.loader import template_source_loaders
66
self.template_does_not_exist = True
67
self.loader_debug_info = []
68
for loader in template_source_loaders:
70
source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources')
71
# NOTE: This assumes exc_value is the name of the template that
72
# the loader attempted to load.
73
template_list = [{'name': t, 'exists': os.path.exists(t)} \
74
for t in source_list_func(str(self.exc_value))]
75
except (ImportError, AttributeError):
77
self.loader_debug_info.append({
78
'loader': loader.__module__ + '.' + loader.__name__,
79
'templates': template_list,
81
if settings.TEMPLATE_DEBUG and hasattr(self.exc_value, 'source'):
82
self.get_template_exception_info()
84
frames = self.get_traceback_frames()
87
if issubclass(self.exc_type, UnicodeError):
88
start = getattr(self.exc_value, 'start', None)
89
end = getattr(self.exc_value, 'end', None)
90
if start is not None and end is not None:
91
unicode_str = self.exc_value.args[1]
92
unicode_hint = smart_unicode(unicode_str[max(start-5, 0):min(end+5, len(unicode_str))], 'ascii', errors='replace')
93
from django import get_version
94
t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
96
'exception_type': self.exc_type.__name__,
97
'exception_value': smart_unicode(self.exc_value, errors='replace'),
98
'unicode_hint': unicode_hint,
100
'lastframe': frames[-1],
101
'request': self.request,
102
'request_protocol': self.request.is_secure() and "https" or "http",
103
'settings': get_safe_settings(),
104
'sys_executable': sys.executable,
105
'sys_version_info': '%d.%d.%d' % sys.version_info[0:3],
106
'server_time': datetime.datetime.now(),
107
'django_version_info': get_version(),
108
'sys_path' : sys.path,
109
'template_info': self.template_info,
110
'template_does_not_exist': self.template_does_not_exist,
111
'loader_debug_info': self.loader_debug_info,
115
def get_template_exception_info(self):
116
origin, (start, end) = self.exc_value.source
117
template_source = origin.reload()
122
before = during = after = ""
123
for num, next in enumerate(linebreak_iter(template_source)):
124
if start >= upto and end <= next:
126
before = escape(template_source[upto:start])
127
during = escape(template_source[start:end])
128
after = escape(template_source[end:next])
129
source_lines.append( (num, escape(template_source[upto:next])) )
131
total = len(source_lines)
133
top = max(1, line - context_lines)
134
bottom = min(total, line + 1 + context_lines)
136
self.template_info = {
137
'message': self.exc_value.args[0],
138
'source_lines': source_lines[top:bottom],
149
def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None):
151
Returns context_lines before and after lineno from file.
152
Returns (pre_context_lineno, pre_context, context_line, post_context).
155
if loader is not None and hasattr(loader, "get_source"):
156
source = loader.get_source(module_name)
157
if source is not None:
158
source = source.splitlines()
78
source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources')
79
# NOTE: This assumes exc_value is the name of the template that
80
# the loader attempted to load.
81
template_list = [{'name': t, 'exists': os.path.exists(t)} \
82
for t in source_list_func(str(exc_value))]
83
except (ImportError, AttributeError):
85
loader_debug_info.append({
86
'loader': loader.__module__ + '.' + loader.__name__,
87
'templates': template_list,
89
if settings.TEMPLATE_DEBUG and hasattr(exc_value, 'source'):
90
exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type, exc_value, tb)
93
filename = tb.tb_frame.f_code.co_filename
94
function = tb.tb_frame.f_code.co_name
95
lineno = tb.tb_lineno - 1
96
pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7)
97
if pre_context_lineno:
100
'filename': filename,
101
'function': function,
102
'lineno': lineno + 1,
103
'vars': tb.tb_frame.f_locals.items(),
105
'pre_context': pre_context,
106
'context_line': context_line,
107
'post_context': post_context,
108
'pre_context_lineno': pre_context_lineno + 1,
114
'filename': '<unknown>',
118
t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
120
'exception_type': exc_type.__name__,
121
'exception_value': exc_value,
123
'lastframe': frames[-1],
125
'request_protocol': request.is_secure() and "https" or "http",
126
'settings': get_safe_settings(),
127
'template_info': template_info,
128
'template_does_not_exist': template_does_not_exist,
129
'loader_debug_info': loader_debug_info,
131
return HttpResponseServerError(t.render(c), mimetype='text/html')
163
source = f.readlines()
166
except (OSError, IOError):
169
return None, [], None, []
172
for line in source[:2]:
173
# File coding may be specified. Match pattern from PEP-263
174
# (http://www.python.org/dev/peps/pep-0263/)
175
match = re.search(r'coding[:=]\s*([-\w.]+)', line)
177
encoding = match.group(1)
179
source = [unicode(sline, encoding, 'replace') for sline in source]
181
lower_bound = max(0, lineno - context_lines)
182
upper_bound = lineno + context_lines
184
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]]
185
context_line = source[lineno].strip('\n')
186
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]]
188
return lower_bound, pre_context, context_line, post_context
190
def get_traceback_frames(self):
193
while tb is not None:
194
# support for __traceback_hide__ which is used by a few libraries
195
# to hide internal frames.
196
if tb.tb_frame.f_locals.get('__traceback_hide__'):
199
filename = tb.tb_frame.f_code.co_filename
200
function = tb.tb_frame.f_code.co_name
201
lineno = tb.tb_lineno - 1
202
loader = tb.tb_frame.f_globals.get('__loader__')
203
module_name = tb.tb_frame.f_globals.get('__name__')
204
pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(filename, lineno, 7, loader, module_name)
205
if pre_context_lineno is not None:
208
'filename': filename,
209
'function': function,
210
'lineno': lineno + 1,
211
'vars': tb.tb_frame.f_locals.items(),
213
'pre_context': pre_context,
214
'context_line': context_line,
215
'post_context': post_context,
216
'pre_context_lineno': pre_context_lineno + 1,
222
'filename': '<unknown>',
225
'context_line': '???',
230
def format_exception(self):
232
Return the same data as from traceback.format_exception.
235
frames = self.get_traceback_frames()
236
tb = [ (f['filename'], f['lineno'], f['function'], f['context_line']) for f in frames ]
237
list = ['Traceback (most recent call last):\n']
238
list += traceback.format_list(tb)
239
list += traceback.format_exception_only(self.exc_type, self.exc_value)
133
243
def technical_404_response(request, exception):
134
244
"Create a technical 404 error response. The exception should be the Http404."
520
<form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
402
521
<div id="pastebinTraceback" class="pastebin">
408
Traceback (most recent call last):<br/>
409
{% for frame in frames %}
410
File "{{ frame.filename }}" in {{ frame.function }}<br/>
411
{% if frame.context_line %}
412
{{ frame.lineno }}. {{ frame.context_line|escape }}<br/>
415
{{ exception_type }} at {{ request.path|escape }}<br/>
416
{{ exception_value|escape }}</code>
522
<input type="hidden" name="language" value="PythonConsole">
523
<input type="hidden" name="title" value="{{ exception_type|escape }} at {{ request.path_info|escape }}">
524
<input type="hidden" name="source" value="Django Dpaste Agent">
525
<input type="hidden" name="poster" value="Django">
526
<textarea name="content" id="traceback_area" cols="140" rows="25">
529
Request Method: {{ request.META.REQUEST_METHOD }}
530
Request URL: {{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path_info|escape }}
531
Django Version: {{ django_version_info }}
532
Python Version: {{ sys_version_info }}
533
Installed Applications:
534
{{ settings.INSTALLED_APPS|pprint }}
535
Installed Middleware:
536
{{ settings.MIDDLEWARE_CLASSES|pprint }}
538
{% if template_does_not_exist %}Template Loader Error:
539
{% if loader_debug_info %}Django tried loading these templates, in this order:
540
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
541
{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %})
542
{% endfor %}{% endfor %}
543
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
545
{% endif %}{% if template_info %}
547
In template {{ template_info.name }}, error at line {{ template_info.line }}
548
{{ template_info.message }}{% for source_line in template_info.source_lines %}{% ifequal source_line.0 template_info.line %}
549
{{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}
551
{{ source_line.0 }} : {{ source_line.1 }}
552
{% endifequal %}{% endfor %}{% endif %}
554
{% for frame in frames %}File "{{ frame.filename|escape }}" in {{ frame.function|escape }}
555
{% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line|escape }}{% endif %}
557
Exception Type: {{ exception_type|escape }} at {{ request.path_info|escape }}
558
Exception Value: {{ exception_value|escape }}
561
<input type="submit" value="Share this traceback on a public Web site">
424
566
<div id="requestinfo">