mirror of
https://github.com/django/django.git
synced 2025-07-03 17:29:12 +00:00
completely switch to repr, added tests for repr exception reports
This commit is contained in:
parent
03c7c2d095
commit
2a977f6705
@ -6,12 +6,12 @@ import reprlib
|
|||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
import warnings
|
import warnings
|
||||||
|
from collections.abc import Sized
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import Http404, HttpResponse, HttpResponseNotFound
|
from django.http import Http404, HttpResponse, HttpResponseNotFound
|
||||||
from django.template import Context, Engine, TemplateDoesNotExist
|
from django.template import Context, Engine, TemplateDoesNotExist
|
||||||
from django.template.defaultfilters import pprint
|
|
||||||
from django.urls import resolve
|
from django.urls import resolve
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
@ -311,8 +311,16 @@ class SafeExceptionReporterFilter:
|
|||||||
class ExceptionReporter:
|
class ExceptionReporter:
|
||||||
"""Organize and coordinate reporting on exceptions."""
|
"""Organize and coordinate reporting on exceptions."""
|
||||||
|
|
||||||
repr_instance = reprlib.Repr(maxstring=4096, maxlist=1000)
|
repr_instance = reprlib.Repr()
|
||||||
MAX_VAR_SIZE_PRETTY_PRINT = 512 * 1024 # 512KB
|
repr_instance.indent = 2
|
||||||
|
repr_instance.maxdeque = 4096
|
||||||
|
repr_instance.maxstring = 4096
|
||||||
|
repr_instance.maxlist = 4096
|
||||||
|
repr_instance.maxset = 4096
|
||||||
|
repr_instance.maxdict = 4096
|
||||||
|
repr_instance.maxfrozenset = 4096
|
||||||
|
repr_instance.maxarray = 4096
|
||||||
|
repr_instance.maxother = 4096
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def html_template_path(self):
|
def html_template_path(self):
|
||||||
@ -352,18 +360,13 @@ class ExceptionReporter:
|
|||||||
self.postmortem = self.exc_value.chain or [self.exc_value]
|
self.postmortem = self.exc_value.chain or [self.exc_value]
|
||||||
|
|
||||||
frames = self.get_traceback_frames()
|
frames = self.get_traceback_frames()
|
||||||
|
|
||||||
for i, frame in enumerate(frames):
|
for i, frame in enumerate(frames):
|
||||||
if "vars" in frame:
|
if "vars" in frame:
|
||||||
frame_vars = []
|
frame_vars = []
|
||||||
for k, v in frame["vars"]:
|
for k, v in frame["vars"]:
|
||||||
if sys.getsizeof(v) > self.MAX_VAR_SIZE_PRETTY_PRINT:
|
if isinstance(v, Sized) and len(v) > 4096:
|
||||||
v = self.repr_instance.repr(v)
|
self.repr_instance.fillvalue = "...%d more" % (len(v) - 4096)
|
||||||
else:
|
v = self.repr_instance.repr(v)
|
||||||
v = pprint(v)
|
|
||||||
# Trim large blobs of data
|
|
||||||
if len(v) > 4096:
|
|
||||||
v = "%s… <trimmed %d bytes string>" % (v[0:4096], len(v))
|
|
||||||
frame_vars.append((k, v))
|
frame_vars.append((k, v))
|
||||||
frame["vars"] = frame_vars
|
frame["vars"] = frame_vars
|
||||||
frames[i] = frame
|
frames[i] = frame
|
||||||
|
0
tests/exception_report/__init__.py
Normal file
0
tests/exception_report/__init__.py
Normal file
51
tests/exception_report/test_large_exception.py
Normal file
51
tests/exception_report/test_large_exception.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
from django.views.debug import ExceptionReporter
|
||||||
|
|
||||||
|
|
||||||
|
class ExceptionReport(TestCase):
|
||||||
|
factory = RequestFactory()
|
||||||
|
|
||||||
|
def test_large_sizable_object(self):
|
||||||
|
lg = list(range(50 * 1024 * 1024))
|
||||||
|
try:
|
||||||
|
request = self.factory.get("/")
|
||||||
|
lg["a"]
|
||||||
|
except TypeError:
|
||||||
|
exc_type, exc_value, tb = sys.exc_info()
|
||||||
|
|
||||||
|
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
|
||||||
|
d = reporter.get_traceback_data()
|
||||||
|
vars = d["lastframe"]["vars"]
|
||||||
|
|
||||||
|
for k, v in vars:
|
||||||
|
if k == "lg":
|
||||||
|
i = v.index("...")
|
||||||
|
# Check if it has been trimmed
|
||||||
|
self.assertGreater(i, -1)
|
||||||
|
|
||||||
|
# Construct list with elements before trimming
|
||||||
|
ls = eval(v[:i] + "]")
|
||||||
|
|
||||||
|
# Check if length of trimmed list is our limit
|
||||||
|
self.assertEqual(len(ls), 4096)
|
||||||
|
break
|
||||||
|
|
||||||
|
def test_non_sizable_object(self):
|
||||||
|
num = 10000000
|
||||||
|
try:
|
||||||
|
request = self.factory.get("/")
|
||||||
|
num["a"]
|
||||||
|
except TypeError:
|
||||||
|
exc_type, exc_value, tb = sys.exc_info()
|
||||||
|
|
||||||
|
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
|
||||||
|
d = reporter.get_traceback_data()
|
||||||
|
vars = d["lastframe"]["vars"]
|
||||||
|
|
||||||
|
for k, v in vars:
|
||||||
|
if k == "a":
|
||||||
|
self.assertEqual(v, str(num))
|
||||||
|
break
|
Loading…
x
Reference in New Issue
Block a user