Commit 5b17dcd8 authored by Tim Heap's avatar Tim Heap Committed by Claude Paroz
Browse files

Fixed #23883 -- Stopped flatatt modifying its argument

parent d8f00e19
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -29,16 +29,17 @@ def flatatt(attrs):

    The result is passed through 'mark_safe'.
    """
    key_value_attrs = []
    boolean_attrs = []
    for attr, value in list(attrs.items()):
        if value is True:
    for attr, value in attrs.items():
        if isinstance(value, bool):
            if value:
                boolean_attrs.append((attr,))
            del attrs[attr]
        elif value is False:
            del attrs[attr]
        else:
            key_value_attrs.append((attr, value))

    return (
        format_html_join('', ' {0}="{1}"', sorted(attrs.items())) +
        format_html_join('', ' {0}="{1}"', sorted(key_value_attrs)) +
        format_html_join('', ' {0}', sorted(boolean_attrs))
    )

+17 −0
Original line number Diff line number Diff line
@@ -27,6 +27,23 @@ class FormsUtilTestCase(TestCase):
        self.assertEqual(flatatt({'class': "news", 'title': "Read this", 'required': False}), ' class="news" title="Read this"')
        self.assertEqual(flatatt({}), '')

    def test_flatatt_no_side_effects(self):
        """
        Fixes #23883 -- Check that flatatt does not modify the dict passed in
        """
        attrs = {'foo': 'bar', 'true': True, 'false': False}
        attrs_copy = copy.copy(attrs)
        self.assertEqual(attrs, attrs_copy)

        first_run = flatatt(attrs)
        self.assertEqual(attrs, attrs_copy)
        self.assertEqual(first_run, ' foo="bar" true')

        second_run = flatatt(attrs)
        self.assertEqual(attrs, attrs_copy)

        self.assertEqual(first_run, second_run)

    def test_validation_error(self):
        ###################
        # ValidationError #