diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..e69de29bb diff --git a/debug_toolbar/forms.py b/debug_toolbar/forms.py index 61444b43c..ca9d1a9b0 100644 --- a/debug_toolbar/forms.py +++ b/debug_toolbar/forms.py @@ -3,7 +3,8 @@ from django import forms from django.core import signing from django.core.exceptions import ValidationError -from django.utils.encoding import force_str + +from debug_toolbar.sanitize import force_str class SignedDataForm(forms.Form): diff --git a/debug_toolbar/panels/settings.py b/debug_toolbar/panels/settings.py index 68ab44c0b..4f91e39fa 100644 --- a/debug_toolbar/panels/settings.py +++ b/debug_toolbar/panels/settings.py @@ -1,8 +1,8 @@ -from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ from django.views.debug import get_default_exception_reporter_filter from debug_toolbar.panels import Panel +from debug_toolbar.sanitize import force_str get_safe_settings = get_default_exception_reporter_filter().get_safe_settings diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py index 45e0c0c17..2cda76d1a 100644 --- a/debug_toolbar/panels/sql/tracking.py +++ b/debug_toolbar/panels/sql/tracking.py @@ -5,8 +5,8 @@ from time import perf_counter import django.test.testcases -from django.utils.encoding import force_str +from debug_toolbar.sanitize import force_str from debug_toolbar.utils import get_stack_trace, get_template_info try: @@ -128,10 +128,7 @@ def _decode(self, param): # make sure datetime, date and time are converted to string by force_str CONVERT_TYPES = (datetime.datetime, datetime.date, datetime.time) - try: - return force_str(param, strings_only=not isinstance(param, CONVERT_TYPES)) - except UnicodeDecodeError: - return "(encoded string)" + return force_str(param, strings_only=not isinstance(param, CONVERT_TYPES)) def _last_executed_query(self, sql, params): """Get the last executed query from the connection.""" diff --git a/debug_toolbar/panels/templates/panel.py b/debug_toolbar/panels/templates/panel.py index 6dbd02ee0..da9c28207 100644 --- a/debug_toolbar/panels/templates/panel.py +++ b/debug_toolbar/panels/templates/panel.py @@ -10,12 +10,12 @@ from django.test.signals import template_rendered from django.test.utils import instrumented_test_render from django.urls import path -from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ from debug_toolbar.panels import Panel from debug_toolbar.panels.sql.tracking import SQLQueryTriggered, allow_sql from debug_toolbar.panels.templates import views +from debug_toolbar.sanitize import force_str if find_spec("jinja2"): from debug_toolbar.panels.templates.jinja2 import patch_jinja_render diff --git a/debug_toolbar/sanitize.py b/debug_toolbar/sanitize.py new file mode 100644 index 000000000..4aaaa1a62 --- /dev/null +++ b/debug_toolbar/sanitize.py @@ -0,0 +1,12 @@ +from django.utils.encoding import DjangoUnicodeDecodeError, force_str as force_string + + +def force_str(s, *args, **kwargs): + """ + Forces values to strings. + Will return "Django Debug Toolbar was unable to parse value." when there's a decoding error. + """ + try: + return force_string(s, *args, **kwargs) + except DjangoUnicodeDecodeError: + return "Django Debug Toolbar was unable to parse value." diff --git a/debug_toolbar/store.py b/debug_toolbar/store.py index 02a2a0f72..b4e32788d 100644 --- a/debug_toolbar/store.py +++ b/debug_toolbar/store.py @@ -6,11 +6,11 @@ from django.core.serializers.json import DjangoJSONEncoder from django.db import transaction -from django.utils.encoding import force_str from django.utils.module_loading import import_string from debug_toolbar import settings as dt_settings from debug_toolbar.models import HistoryEntry +from debug_toolbar.sanitize import force_str class DebugToolbarJSONEncoder(DjangoJSONEncoder): diff --git a/docs/changes.rst b/docs/changes.rst index 352b4f946..667251b4f 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -16,6 +16,9 @@ Pending * Upgraded CI ``postgis`` version to 17-3.5. * Added how to generate the documentation locally to the contributing documentation. +* Updated logic that forces values to strings (``force_str``) to render + "Django Debug Toolbar was unable to parse value." when there's a decoding + error. 6.0.0 (2025-07-22) ------------------ diff --git a/tests/test_sanitize.py b/tests/test_sanitize.py new file mode 100644 index 000000000..539980bd3 --- /dev/null +++ b/tests/test_sanitize.py @@ -0,0 +1,18 @@ +import unittest + +from debug_toolbar.sanitize import force_str + + +class ForceStrTestCase(unittest.TestCase): + def test_success_convert(self): + input = 0 + + self.assertEqual(force_str(input), "0") + + def test_failed_convert(self): + input = bytes.fromhex( + "a3f2b8c14e972d5a8fb3c7291a64e0859c472bf63d18a0945e73b2c84f917ae2" + ) + self.assertEqual( + force_str(input), "Django Debug Toolbar was unable to parse value." + )