commit d71e54a8bba804fe10a8919fe21d0f2fae7cdc52
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sat Jan 4 20:52:24 2014 +0100
Fixed #21733 -- Infinite recursion in @python_2_unicode_compatible.
Applying the decorator twice to the same class now raises an exception
instead of triggering an infinite recursion.
Thanks ntucker for the report.
diff --git a/django/utils/encoding.py b/django/utils/encoding.py
index ee67df3..8a32d7f 100644
a
|
b
|
def python_2_unicode_compatible(klass):
|
34 | 34 | raise ValueError("@python_2_unicode_compatible cannot be applied " |
35 | 35 | "to %s because it doesn't define __str__()." % |
36 | 36 | klass.__name__) |
| 37 | elif hasattr(klass.__str__, '_python_2_unicode_compatible'): |
| 38 | raise ValueError("@python_2_unicode_compatible was already " |
| 39 | "applied to %s." % klass.__name__) |
37 | 40 | klass.__unicode__ = klass.__str__ |
38 | | klass.__str__ = lambda self: self.__unicode__().encode('utf-8') |
| 41 | def new_str(self): |
| 42 | return klass.__unicode__(self).encode('utf-8') |
| 43 | new_str._python_2_unicode_compatible = None |
| 44 | klass.__str__ = new_str |
39 | 45 | return klass |
40 | 46 | |
41 | 47 | |
diff --git a/tests/utils_tests/test_encoding.py b/tests/utils_tests/test_encoding.py
index a91f596..1516637 100644
a
|
b
|
|
1 | 1 | # -*- encoding: utf-8 -*- |
| 2 | |
2 | 3 | from __future__ import unicode_literals |
3 | 4 | |
4 | 5 | import unittest |
… |
… |
class TestEncodingUtils(unittest.TestCase):
|
47 | 48 | |
48 | 49 | @unittest.skipIf(six.PY3, "tests a class not defining __str__ under Python 2") |
49 | 50 | def test_decorated_class_without_str(self): |
50 | | with self.assertRaises(ValueError): |
| 51 | with six.assertRaisesRegex(self, ValueError, "doesn't define __str__"): |
51 | 52 | @python_2_unicode_compatible |
52 | 53 | class NoStr(object): |
53 | 54 | pass |
| 55 | |
| 56 | @unittest.skipIf(six.PY3, "tests a class not redefining __str__ under Python 2") |
| 57 | def test_twice_decorated_class(self): |
| 58 | with six.assertRaisesRegex(self, ValueError, "already applied"): |
| 59 | @python_2_unicode_compatible |
| 60 | @python_2_unicode_compatible |
| 61 | class Str(object): |
| 62 | def __str__(self): |
| 63 | return b'' |