mirror of https://github.com/django/django.git
Fixed #33747 -- Added exception notes to the technical 500 debug page.
This commit is contained in:
parent
70c945d6b3
commit
80c66e40f7
|
@ -396,6 +396,8 @@ class ExceptionReporter:
|
||||||
c["exception_type"] = self.exc_type.__name__
|
c["exception_type"] = self.exc_type.__name__
|
||||||
if self.exc_value:
|
if self.exc_value:
|
||||||
c["exception_value"] = str(self.exc_value)
|
c["exception_value"] = str(self.exc_value)
|
||||||
|
if exc_notes := getattr(self.exc_value, "__notes__", None):
|
||||||
|
c["exception_notes"] = "\n" + "\n".join(exc_notes)
|
||||||
if frames:
|
if frames:
|
||||||
c["lastframe"] = frames[-1]
|
c["lastframe"] = frames[-1]
|
||||||
return c
|
return c
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
<div id="summary">
|
<div id="summary">
|
||||||
<h1>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}
|
<h1>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}
|
||||||
{% if request %} at {{ request.path_info }}{% endif %}</h1>
|
{% if request %} at {{ request.path_info }}{% endif %}</h1>
|
||||||
<pre class="exception_value">{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}</pre>
|
<pre class="exception_value">{% if exception_value %}{{ exception_value|force_escape }}{% if exception_notes %}{{ exception_notes }}{% endif %}{% else %}No exception message supplied{% endif %}</pre>
|
||||||
<table class="meta">
|
<table class="meta">
|
||||||
{% if request %}
|
{% if request %}
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -330,7 +330,7 @@ During handling of the above exception ({{ frame.exc_cause|force_escape }}), ano
|
||||||
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% elif forloop.first %}None{% else %}Traceback: None{% endif %}{% endfor %}
|
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% elif forloop.first %}None{% else %}Traceback: None{% endif %}{% endfor %}
|
||||||
|
|
||||||
Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
|
Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
|
||||||
Exception Value: {{ exception_value|force_escape }}
|
Exception Value: {{ exception_value|force_escape }}{% if exception_notes %}{{ exception_notes }}{% endif %}
|
||||||
</textarea>
|
</textarea>
|
||||||
<br><br>
|
<br><br>
|
||||||
<input type="submit" value="Share this traceback on a public website">
|
<input type="submit" value="Share this traceback on a public website">
|
||||||
|
|
|
@ -34,7 +34,7 @@ Traceback (most recent call last):
|
||||||
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% elif forloop.first %}None{% else %}Traceback: None{% endif %}
|
{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{% endif %}{% elif forloop.first %}None{% else %}Traceback: None{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
|
{% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
|
||||||
{% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% endif %}{% endif %}
|
{% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% if exception_notes %}{{ exception_notes }}{% endif %}{% endif %}{% endif %}
|
||||||
{% if raising_view_name %}Raised during: {{ raising_view_name }}{% endif %}
|
{% if raising_view_name %}Raised during: {{ raising_view_name }}{% endif %}
|
||||||
{% if request %}Request information:
|
{% if request %}Request information:
|
||||||
{% if user_str %}USER: {{ user_str }}{% endif %}
|
{% if user_str %}USER: {{ user_str }}{% endif %}
|
||||||
|
|
|
@ -158,7 +158,7 @@ Email
|
||||||
Error Reporting
|
Error Reporting
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* The debug page now shows :pep:`exception notes <678>` on Python 3.11+.
|
||||||
|
|
||||||
File Storage
|
File Storage
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
|
@ -7,7 +7,7 @@ import tempfile
|
||||||
import threading
|
import threading
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock, skipIf
|
from unittest import mock, skipIf, skipUnless
|
||||||
|
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
|
@ -22,6 +22,7 @@ from django.urls.converters import IntConverter
|
||||||
from django.utils.functional import SimpleLazyObject
|
from django.utils.functional import SimpleLazyObject
|
||||||
from django.utils.regex_helper import _lazy_re_compile
|
from django.utils.regex_helper import _lazy_re_compile
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
from django.utils.version import PY311
|
||||||
from django.views.debug import (
|
from django.views.debug import (
|
||||||
CallableSettingWrapper,
|
CallableSettingWrapper,
|
||||||
ExceptionCycleWarning,
|
ExceptionCycleWarning,
|
||||||
|
@ -659,6 +660,40 @@ class ExceptionReporterTests(SimpleTestCase):
|
||||||
text,
|
text,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@skipUnless(PY311, "Exception notes were added in Python 3.11.")
|
||||||
|
def test_exception_with_notes(self):
|
||||||
|
request = self.rf.get("/test_view/")
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
raise RuntimeError("Oops")
|
||||||
|
except Exception as err:
|
||||||
|
err.add_note("First Note")
|
||||||
|
err.add_note("Second Note")
|
||||||
|
err.add_note(mark_safe("<script>alert(1);</script>"))
|
||||||
|
raise err
|
||||||
|
except Exception:
|
||||||
|
exc_type, exc_value, tb = sys.exc_info()
|
||||||
|
|
||||||
|
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
|
||||||
|
html = reporter.get_traceback_html()
|
||||||
|
self.assertIn(
|
||||||
|
'<pre class="exception_value">Oops\nFirst Note\nSecond Note\n'
|
||||||
|
"<script>alert(1);</script></pre>",
|
||||||
|
html,
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
"Exception Value: Oops\nFirst Note\nSecond Note\n"
|
||||||
|
"<script>alert(1);</script>",
|
||||||
|
html,
|
||||||
|
)
|
||||||
|
|
||||||
|
text = reporter.get_traceback_text()
|
||||||
|
self.assertIn(
|
||||||
|
"Exception Value: Oops\nFirst Note\nSecond Note\n"
|
||||||
|
"<script>alert(1);</script>",
|
||||||
|
text,
|
||||||
|
)
|
||||||
|
|
||||||
def test_mid_stack_exception_without_traceback(self):
|
def test_mid_stack_exception_without_traceback(self):
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue