mirror of
https://github.com/django/django.git
synced 2025-01-03 06:55:47 +00:00
Fixed #35648 -- Raised NotImplementedError in SafeString.__add__ for non-string RHS.
This change ensures SafeString addition operations handle non-string RHS properly, allowing them to implement __radd__ for better compatibility.
This commit is contained in:
parent
b5c048f5ec
commit
d84200e4eb
@ -35,11 +35,17 @@ class SafeString(str, SafeData):
|
|||||||
Concatenating a safe string with another safe bytestring or
|
Concatenating a safe string with another safe bytestring or
|
||||||
safe string is safe. Otherwise, the result is no longer safe.
|
safe string is safe. Otherwise, the result is no longer safe.
|
||||||
"""
|
"""
|
||||||
|
if isinstance(rhs, str):
|
||||||
t = super().__add__(rhs)
|
t = super().__add__(rhs)
|
||||||
if isinstance(rhs, SafeData):
|
if isinstance(rhs, SafeData):
|
||||||
return SafeString(t)
|
t = SafeString(t)
|
||||||
return t
|
return t
|
||||||
|
|
||||||
|
# Give the rhs object a chance to handle the addition, for example if
|
||||||
|
# the rhs object's class implements `__radd__`. More details:
|
||||||
|
# https://docs.python.org/3/reference/datamodel.html#object.__radd__
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -262,7 +262,10 @@ URLs
|
|||||||
Utilities
|
Utilities
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* :class:`~django.utils.safestring.SafeString` now raises
|
||||||
|
:exc:`NotImplementedError` in ``__add__`` for non-string right-hand side
|
||||||
|
values. This aligns with the :py:class:`str` addition behavior and allows
|
||||||
|
``__radd__`` to be used if available.
|
||||||
|
|
||||||
Validators
|
Validators
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
@ -132,3 +132,54 @@ class SafeStringTest(SimpleTestCase):
|
|||||||
for case, expected in cases:
|
for case, expected in cases:
|
||||||
with self.subTest(case=case):
|
with self.subTest(case=case):
|
||||||
self.assertRenderEqual("{{ s }}", expected, s=s + case)
|
self.assertRenderEqual("{{ s }}", expected, s=s + case)
|
||||||
|
|
||||||
|
def test_add_obj(self):
|
||||||
|
|
||||||
|
base_str = "<strong>strange</strong>"
|
||||||
|
add_str = "hello</br>"
|
||||||
|
|
||||||
|
class Add:
|
||||||
|
def __add__(self, other):
|
||||||
|
return base_str + other
|
||||||
|
|
||||||
|
class AddSafe:
|
||||||
|
def __add__(self, other):
|
||||||
|
return mark_safe(base_str) + other
|
||||||
|
|
||||||
|
class Radd:
|
||||||
|
def __radd__(self, other):
|
||||||
|
return other + base_str
|
||||||
|
|
||||||
|
class RaddSafe:
|
||||||
|
def __radd__(self, other):
|
||||||
|
return other + mark_safe(base_str)
|
||||||
|
|
||||||
|
left_add_expected = f"{base_str}{add_str}"
|
||||||
|
right_add_expected = f"{add_str}{base_str}"
|
||||||
|
cases = [
|
||||||
|
# Left-add test cases.
|
||||||
|
(Add(), add_str, left_add_expected, str),
|
||||||
|
(Add(), mark_safe(add_str), left_add_expected, str),
|
||||||
|
(AddSafe(), add_str, left_add_expected, str),
|
||||||
|
(AddSafe(), mark_safe(add_str), left_add_expected, SafeString),
|
||||||
|
# Right-add test cases.
|
||||||
|
(add_str, Radd(), right_add_expected, str),
|
||||||
|
(mark_safe(add_str), Radd(), right_add_expected, str),
|
||||||
|
(add_str, Radd(), right_add_expected, str),
|
||||||
|
(mark_safe(add_str), RaddSafe(), right_add_expected, SafeString),
|
||||||
|
]
|
||||||
|
for lhs, rhs, expected, expected_type in cases:
|
||||||
|
with self.subTest(lhs=lhs, rhs=rhs):
|
||||||
|
result = lhs + rhs
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertEqual(type(result), expected_type)
|
||||||
|
|
||||||
|
cases = [
|
||||||
|
("hello", Add()),
|
||||||
|
("hello", AddSafe()),
|
||||||
|
(Radd(), "hello"),
|
||||||
|
(RaddSafe(), "hello"),
|
||||||
|
]
|
||||||
|
for lhs, rhs in cases:
|
||||||
|
with self.subTest(lhs=lhs, rhs=rhs), self.assertRaises(TypeError):
|
||||||
|
lhs + rhs
|
||||||
|
Loading…
Reference in New Issue
Block a user