Commit 082abce8 authored by Loic Bistuer's avatar Loic Bistuer
Browse files

[1.7.x] Fixed #23594 -- Fixed deepcopy on ErrorList.

Thanks Troy Grosfield for the report and Tim Graham for the tests.

Backport of ec2fd02b from master
parent 2999bf05
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -131,6 +131,15 @@ class ErrorList(UserList, list):
            return list(error)[0]
        return force_text(error)

    def __reduce_ex__(self, *args, **kwargs):
        # The `list` reduce function returns an iterator as the fourth element
        # that is normally used for repopulating. Since we only inherit from
        # `list` for `isinstance` backward compatibility (Refs #17413) we
        # nullify this iterator as it would otherwise result in duplicate
        # entries. (Refs #23594)
        info = super(UserList, self).__reduce_ex__(*args, **kwargs)
        return info[:3] + (None, None)


# Utilities for time zone support in DateTimeField et al.

+2 −0
Original line number Diff line number Diff line
@@ -89,3 +89,5 @@ Bugfixes

* Fixed ``MigrationWriter`` to handle builtin types without imports
  (:ticket:`23560`).

* Fixed ``deepcopy`` on ``ErrorList`` (:ticket:`23594`).
+23 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import copy

from django.core.exceptions import ValidationError
from django.forms.utils import flatatt, ErrorDict, ErrorList
from django.test import TestCase
@@ -66,3 +68,24 @@ class FormsUtilTestCase(TestCase):
                         '<ul class="errorlist"><li>nameExample of link: &lt;a href=&quot;http://www.example.com/&quot;&gt;example&lt;/a&gt;</li></ul>')
        self.assertHTMLEqual(str(ErrorDict({'name': mark_safe(example)})),
                         '<ul class="errorlist"><li>nameExample of link: <a href="http://www.example.com/">example</a></li></ul>')

    def test_error_dict_copy(self):
        e = ErrorDict()
        e['__all__'] = ErrorList([
            ValidationError(
                message='message %(i)s',
                params={'i': 1},
            ),
            ValidationError(
                message='message %(i)s',
                params={'i': 2},
            ),
        ])

        e_copy = copy.copy(e)
        self.assertEqual(e, e_copy)
        self.assertEqual(e.as_data(), e_copy.as_data())

        e_deepcopy = copy.deepcopy(e)
        self.assertEqual(e, e_deepcopy)
        self.assertEqual(e.as_data(), e_copy.as_data())