1
0
mirror of https://github.com/django/django.git synced 2025-06-08 21:19:13 +00:00

completely switch to repr, added tests for repr exception reports

This commit is contained in:
Keerthi Vasan 2024-02-02 16:15:12 +05:30
parent 03c7c2d095
commit 2a977f6705
3 changed files with 65 additions and 11 deletions

View File

@ -6,12 +6,12 @@ import reprlib
import sys
import types
import warnings
from collections.abc import Sized
from pathlib import Path
from django.conf import settings
from django.http import Http404, HttpResponse, HttpResponseNotFound
from django.template import Context, Engine, TemplateDoesNotExist
from django.template.defaultfilters import pprint
from django.urls import resolve
from django.utils import timezone
from django.utils.datastructures import MultiValueDict
@ -311,8 +311,16 @@ class SafeExceptionReporterFilter:
class ExceptionReporter:
"""Organize and coordinate reporting on exceptions."""
repr_instance = reprlib.Repr(maxstring=4096, maxlist=1000)
MAX_VAR_SIZE_PRETTY_PRINT = 512 * 1024 # 512KB
repr_instance = reprlib.Repr()
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
def html_template_path(self):
@ -352,18 +360,13 @@ class ExceptionReporter:
self.postmortem = self.exc_value.chain or [self.exc_value]
frames = self.get_traceback_frames()
for i, frame in enumerate(frames):
if "vars" in frame:
frame_vars = []
for k, v in frame["vars"]:
if sys.getsizeof(v) > self.MAX_VAR_SIZE_PRETTY_PRINT:
v = self.repr_instance.repr(v)
else:
v = pprint(v)
# Trim large blobs of data
if len(v) > 4096:
v = "%s… <trimmed %d bytes string>" % (v[0:4096], len(v))
if isinstance(v, Sized) and len(v) > 4096:
self.repr_instance.fillvalue = "...%d more" % (len(v) - 4096)
v = self.repr_instance.repr(v)
frame_vars.append((k, v))
frame["vars"] = frame_vars
frames[i] = frame

View File

View 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