Fixed #23594 -- Fixed deepcopy on ErrorList.

Thanks Troy Grosfield for the report and Tim Graham for the tests.
This commit is contained in:
Loic Bistuer 2014-10-07 00:09:21 +07:00
parent 1edaa55201
commit ec2fd02bb3
3 changed files with 34 additions and 0 deletions

View File

@ -138,6 +138,15 @@ class ErrorList(UserList, list):
return list(error)[0] return list(error)[0]
return force_text(error) 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. # Utilities for time zone support in DateTimeField et al.

View File

@ -89,3 +89,5 @@ Bugfixes
* Fixed ``MigrationWriter`` to handle builtin types without imports * Fixed ``MigrationWriter`` to handle builtin types without imports
(:ticket:`23560`). (:ticket:`23560`).
* Fixed ``deepcopy`` on ``ErrorList`` (:ticket:`23594`).

View File

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import copy
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.utils import flatatt, ErrorDict, ErrorList from django.forms.utils import flatatt, ErrorDict, ErrorList
from django.test import TestCase from django.test import TestCase
@ -69,3 +71,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>') '<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)})), 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>') '<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())