From 71d39571f46701a5a65adf8bf21005a177cda11f Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Thu, 10 Aug 2017 02:01:33 +0100 Subject: [PATCH] Fixed #28485 -- Made ExceptionReporter.get_traceback_frames() include frames without source code. --- AUTHORS | 1 + django/views/debug.py | 36 +++++++++++++++------------- tests/view_tests/tests/test_debug.py | 21 ++++++++++++++++ 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0f20d4ff6f..c500d08686 100644 --- a/AUTHORS +++ b/AUTHORS @@ -514,6 +514,7 @@ answer newbie questions, and generally made Django that much better: Martin Kosír Martin Mahner Martin Maney + Martin von Gagern Mart Sõmermaa Marty Alchin masonsimon+django@gmail.com diff --git a/django/views/debug.py b/django/views/debug.py index 9823b7dd8c..fca137fd07 100644 --- a/django/views/debug.py +++ b/django/views/debug.py @@ -418,22 +418,26 @@ class ExceptionReporter: pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file( filename, lineno, 7, loader, module_name, ) - if pre_context_lineno is not None: - frames.append({ - 'exc_cause': explicit_or_implicit_cause(exc_value), - 'exc_cause_explicit': getattr(exc_value, '__cause__', True), - 'tb': tb, - 'type': 'django' if module_name.startswith('django.') else 'user', - 'filename': filename, - 'function': function, - 'lineno': lineno + 1, - 'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame), - 'id': id(tb), - 'pre_context': pre_context, - 'context_line': context_line, - 'post_context': post_context, - 'pre_context_lineno': pre_context_lineno + 1, - }) + if pre_context_lineno is None: + pre_context_lineno = lineno + pre_context = [] + context_line = '' + post_context = [] + frames.append({ + 'exc_cause': explicit_or_implicit_cause(exc_value), + 'exc_cause_explicit': getattr(exc_value, '__cause__', True), + 'tb': tb, + 'type': 'django' if module_name.startswith('django.') else 'user', + 'filename': filename, + 'function': function, + 'lineno': lineno + 1, + 'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame), + '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 # other exception. diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py index a260f948e5..8de484d6a9 100644 --- a/tests/view_tests/tests/test_debug.py +++ b/tests/view_tests/tests/test_debug.py @@ -375,6 +375,27 @@ class ExceptionReporterTests(SimpleTestCase): self.assertIn(implicit_exc.format("Second exception"), text) self.assertEqual(3, text.count('

Final exception

')) + 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'], '') + 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): "A message can be provided in addition to a request" request = self.rf.get('/test_view/')