Fixed #28485 -- Made ExceptionReporter.get_traceback_frames() include frames without source code.

This commit is contained in:
Martin von Gagern 2017-08-10 02:01:33 +01:00 committed by Tim Graham
parent 90d7b912b9
commit 71d39571f4
3 changed files with 42 additions and 16 deletions

View File

@ -514,6 +514,7 @@ answer newbie questions, and generally made Django that much better:
Martin Kosír <martin@martinkosir.net> Martin Kosír <martin@martinkosir.net>
Martin Mahner <http://www.mahner.org/> Martin Mahner <http://www.mahner.org/>
Martin Maney <http://www.chipy.org/Martin_Maney> Martin Maney <http://www.chipy.org/Martin_Maney>
Martin von Gagern <gagern@google.com>
Mart Sõmermaa <http://mrts.pri.ee/> Mart Sõmermaa <http://mrts.pri.ee/>
Marty Alchin <gulopine@gamemusic.org> Marty Alchin <gulopine@gamemusic.org>
masonsimon+django@gmail.com masonsimon+django@gmail.com

View File

@ -418,22 +418,26 @@ class ExceptionReporter:
pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file( pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(
filename, lineno, 7, loader, module_name, filename, lineno, 7, loader, module_name,
) )
if pre_context_lineno is not None: if pre_context_lineno is None:
frames.append({ pre_context_lineno = lineno
'exc_cause': explicit_or_implicit_cause(exc_value), pre_context = []
'exc_cause_explicit': getattr(exc_value, '__cause__', True), context_line = '<source code not available>'
'tb': tb, post_context = []
'type': 'django' if module_name.startswith('django.') else 'user', frames.append({
'filename': filename, 'exc_cause': explicit_or_implicit_cause(exc_value),
'function': function, 'exc_cause_explicit': getattr(exc_value, '__cause__', True),
'lineno': lineno + 1, 'tb': tb,
'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame), 'type': 'django' if module_name.startswith('django.') else 'user',
'id': id(tb), 'filename': filename,
'pre_context': pre_context, 'function': function,
'context_line': context_line, 'lineno': lineno + 1,
'post_context': post_context, 'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame),
'pre_context_lineno': pre_context_lineno + 1, 'id': id(tb),
}) 'pre_context': pre_context,
'context_line': context_line,
'post_context': post_context,
'pre_context_lineno': pre_context_lineno + 1,
})
# If the traceback for current exception is consumed, try the # If the traceback for current exception is consumed, try the
# other exception. # other exception.

View File

@ -375,6 +375,27 @@ class ExceptionReporterTests(SimpleTestCase):
self.assertIn(implicit_exc.format("Second exception"), text) self.assertIn(implicit_exc.format("Second exception"), text)
self.assertEqual(3, text.count('<p>Final exception</p>')) self.assertEqual(3, text.count('<p>Final exception</p>'))
def test_reporting_frames_without_source(self):
try:
source = "def funcName():\n raise Error('Whoops')\nfuncName()"
namespace = {}
code = compile(source, 'generated', 'exec')
exec(code, namespace)
except Exception:
exc_type, exc_value, tb = sys.exc_info()
request = self.rf.get('/test_view/')
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
frames = reporter.get_traceback_frames()
last_frame = frames[-1]
self.assertEqual(last_frame['context_line'], '<source code not available>')
self.assertEqual(last_frame['filename'], 'generated')
self.assertEqual(last_frame['function'], 'funcName')
self.assertEqual(last_frame['lineno'], 2)
html = reporter.get_traceback_html()
self.assertIn('generated in funcName', html)
text = reporter.get_traceback_text()
self.assertIn('"generated" in funcName', text)
def test_request_and_message(self): def test_request_and_message(self):
"A message can be provided in addition to a request" "A message can be provided in addition to a request"
request = self.rf.get('/test_view/') request = self.rf.get('/test_view/')