Fixed #20296 -- Prevented mark_safe() from evaluating lazy objects.

This commit is contained in:
Theo Alexiou 2022-02-18 20:27:05 +01:00 committed by Mariusz Felisiak
parent b626c5a979
commit 659d2421c7
3 changed files with 18 additions and 5 deletions

View File

@ -7,6 +7,8 @@ be interpreted by the HTML engine (e.g. '<') into the appropriate entities.
from functools import wraps
from django.utils.functional import keep_lazy
class SafeData:
__slots__ = ()
@ -53,6 +55,7 @@ def _safety_decorator(safety_marker, func):
return wrapped
@keep_lazy(SafeString)
def mark_safe(s):
"""
Explicitly mark a string as safe for (HTML) output purposes. The returned

View File

@ -312,6 +312,8 @@ Utilities
* ``SimpleLazyObject`` now supports addition operations.
* :func:`~django.utils.safestring.mark_safe` now preserves lazy objects.
Validators
~~~~~~~~~~

View File

@ -1,8 +1,9 @@
from django.template import Context, Template
from django.test import SimpleTestCase
from django.utils import html
from django.utils.functional import lazy, lazystr
from django.utils import html, translation
from django.utils.functional import Promise, lazy, lazystr
from django.utils.safestring import SafeData, SafeString, mark_safe
from django.utils.translation import gettext_lazy
class customescape(str):
@ -40,10 +41,17 @@ class SafeStringTest(SimpleTestCase):
self.assertRenderEqual("{{ s|force_escape }}", "&lt;a&amp;b&gt;", s=s)
def test_mark_safe_lazy(self):
s = lazystr("a&b")
safe_s = mark_safe(lazystr("a&b"))
self.assertIsInstance(mark_safe(s), SafeData)
self.assertRenderEqual("{{ s }}", "a&b", s=mark_safe(s))
self.assertIsInstance(safe_s, Promise)
self.assertRenderEqual("{{ s }}", "a&b", s=safe_s)
self.assertIsInstance(str(safe_s), SafeData)
def test_mark_safe_lazy_i18n(self):
s = mark_safe(gettext_lazy("name"))
tpl = Template("{{ s }}")
with translation.override("fr"):
self.assertEqual(tpl.render(Context({"s": s})), "nom")
def test_mark_safe_object_implementing_dunder_str(self):
class Obj: