Skip to content

Commit

Permalink
Refs #31672 -- Made technical 500 debug page include exceptions witho…
Browse files Browse the repository at this point in the history
…ut tracebacks.
  • Loading branch information
hramezani authored and felixxm committed Nov 10, 2020
1 parent a43e2f6 commit 4cd77f9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
8 changes: 7 additions & 1 deletion django/views/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,13 @@ def get_traceback_frames(self):
def get_exception_traceback_frames(self, exc_value, tb):
exc_cause = self._get_explicit_or_implicit_cause(exc_value)
exc_cause_explicit = getattr(exc_value, '__cause__', True)

if tb is None:
yield {
'exc_cause': exc_cause,
'exc_cause_explicit': exc_cause_explicit,
'tb': None,
'type': 'user',
}
while tb is not None:
# Support for __traceback_hide__ which is used by a few libraries
# to hide internal frames.
Expand Down
10 changes: 7 additions & 3 deletions django/views/templates/technical_500.html
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ <h2>Traceback{% if not is_email %} <span class="commands"><a href="#" onclick="r
</h3></li>
{% endif %}{% endifchanged %}
<li class="frame {{ frame.type }}">
<code class="fname">{{ frame.filename }}</code>, line {{ frame.lineno }}, in {{ frame.function }}
{% if not frame.tb %}
{% if forloop.first %}None{% else %}Traceback: None{% endif %}
{% else %}
<code class="fname">{{ frame.filename }}</code>, line {{ frame.lineno }}, in {{ frame.function }}
{% endif %}

{% if frame.context_line %}
<div class="context" id="c{{ frame.id }}">
Expand Down Expand Up @@ -319,8 +323,8 @@ <h2>Local Vars</h2>
The above exception ({{ frame.exc_cause|force_escape }}) was the direct cause of the following exception:
{% else %}
During handling of the above exception ({{ frame.exc_cause|force_escape }}), another exception occurred:
{% endif %}{% endif %}{% endifchanged %} File "{{ frame.filename }}"{% if frame.context_line %}, line {{ frame.lineno }}{% endif %}, in {{ frame.function }}
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% endfor %}
{% endif %}{% endif %}{% endifchanged %} {% if frame.tb %}File "{{ frame.filename }}"{% if frame.context_line %}, line {{ frame.lineno }}{% endif %}, in {{ frame.function }}
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% else %}{% if forloop.first %}None{% else %}Traceback: None{% endif %}{% endif %}{% endfor %}

Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
Exception Value: {{ exception_value|force_escape }}
Expand Down
4 changes: 2 additions & 2 deletions django/views/templates/technical_500.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ In template {{ template_info.name }}, error at line {{ template_info.line }}
Traceback (most recent call last):
{% for frame in frames %}{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}
{% if frame.exc_cause_explicit %}The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:{% else %}During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:{% endif %}
{% endif %}{% endifchanged %} File "{{ frame.filename }}"{% if frame.context_line %}, line {{ frame.lineno }}{% endif %}, in {{ frame.function }}
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}
{% endif %}{% endifchanged %} {% if frame.tb %}File "{{ frame.filename }}"{% if frame.context_line %}, line {{ frame.lineno }}{% endif %}, in {{ frame.function }}
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% else %}{% if forloop.first %}None{% else %}Traceback: None{% endif %}{% endif %}
{% endfor %}
{% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
{% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% endif %}{% endif %}
Expand Down
52 changes: 49 additions & 3 deletions tests/view_tests/tests/test_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ def test_innermost_exception_without_traceback(self):

reporter = ExceptionReporter(None, exc_type, exc_value, tb)
frames = reporter.get_traceback_frames()
self.assertEqual(len(frames), 1)
self.assertEqual(len(frames), 2)
html = reporter.get_traceback_html()
self.assertInHTML('<h1>RuntimeError</h1>', html)
self.assertIn('<pre class="exception_value">Oops</pre>', html)
Expand All @@ -508,6 +508,52 @@ def test_innermost_exception_without_traceback(self):
'exception occurred',
html,
)
self.assertInHTML('<li class="frame user">None</li>', html)
self.assertIn('Traceback (most recent call last):\n None', html)

text = reporter.get_traceback_text()
self.assertIn('Exception Type: RuntimeError', text)
self.assertIn('Exception Value: Oops', text)
self.assertIn('Traceback (most recent call last):\n None', text)
self.assertIn(
'During handling of the above exception (My context), another '
'exception occurred',
text,
)

def test_mid_stack_exception_without_traceback(self):
try:
try:
raise RuntimeError('Inner Oops')
except Exception as exc:
new_exc = RuntimeError('My context')
new_exc.__context__ = exc
raise RuntimeError('Oops') from new_exc
except Exception:
exc_type, exc_value, tb = sys.exc_info()
reporter = ExceptionReporter(None, exc_type, exc_value, tb)
html = reporter.get_traceback_html()
self.assertInHTML('<h1>RuntimeError</h1>', html)
self.assertIn('<pre class="exception_value">Oops</pre>', html)
self.assertIn('<th>Exception Type:</th>', html)
self.assertIn('<th>Exception Value:</th>', html)
self.assertIn('<h2>Traceback ', html)
self.assertInHTML('<li class="frame user">Traceback: None</li>', html)
self.assertIn(
'During handling of the above exception (Inner Oops), another '
'exception occurred:\n Traceback: None',
html,
)

text = reporter.get_traceback_text()
self.assertIn('Exception Type: RuntimeError', text)
self.assertIn('Exception Value: Oops', text)
self.assertIn('Traceback (most recent call last):', text)
self.assertIn(
'During handling of the above exception (Inner Oops), another '
'exception occurred:\n Traceback: None',
text,
)

def test_reporting_of_nested_exceptions(self):
request = self.rf.get('/test_view/')
Expand Down Expand Up @@ -671,7 +717,7 @@ def test_request_and_message(self):
self.assertIn('<th>Request URL:</th>', html)
self.assertNotIn('<th>Exception Type:</th>', html)
self.assertNotIn('<th>Exception Value:</th>', html)
self.assertNotIn('<h2>Traceback ', html)
self.assertIn('<h2>Traceback ', html)
self.assertIn('<h2>Request information</h2>', html)
self.assertNotIn('<p>Request data not supplied</p>', html)

Expand All @@ -684,7 +730,7 @@ def test_message_only(self):
self.assertNotIn('<th>Request URL:</th>', html)
self.assertNotIn('<th>Exception Type:</th>', html)
self.assertNotIn('<th>Exception Value:</th>', html)
self.assertNotIn('<h2>Traceback ', html)
self.assertIn('<h2>Traceback ', html)
self.assertIn('<h2>Request information</h2>', html)
self.assertIn('<p>Request data not supplied</p>', html)

Expand Down

0 comments on commit 4cd77f9

Please sign in to comment.