Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #21198 -- Prevented invalid use of @python_2_unicode_compatible.

Thanks jpic for the report and chmodas for working on a patch.

Reverts 2ea80b9. Refs #19362.

Conflicts:
	tests/utils_tests/test_encoding.py
  • Loading branch information...
commit f0c7649b1692f8441eb9b9b923b2bed8e95f9185 1 parent ddff652
Aymeric Augustin authored October 13, 2013
5  django/db/models/base.py
@@ -427,11 +427,6 @@ def __repr__(self):
427 427
 
428 428
     def __str__(self):
429 429
         if six.PY2 and hasattr(self, '__unicode__'):
430  
-            if type(self).__unicode__ == Model.__str__:
431  
-                klass_name = type(self).__name__
432  
-                raise RuntimeError("%s.__unicode__ is aliased to __str__. Did"
433  
-                                   " you apply @python_2_unicode_compatible"
434  
-                                   " without defining __str__?" % klass_name)
435 430
             return force_text(self).encode('utf-8')
436 431
         return '%s object' % self.__class__.__name__
437 432
 
4  django/utils/encoding.py
@@ -52,6 +52,10 @@ def python_2_unicode_compatible(klass):
52 52
     returning text and apply this decorator to the class.
53 53
     """
54 54
     if six.PY2:
  55
+        if '__str__' not in klass.__dict__:
  56
+            raise ValueError("@python_2_unicode_compatible cannot be applied "
  57
+                             "to %s because it doesn't define __str__()." %
  58
+                             klass.__name__)
55 59
         klass.__unicode__ = klass.__str__
56 60
         klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
57 61
     return klass
3  tests/commands_sql/models.py
... ...
@@ -1,13 +1,10 @@
1 1
 from django.db import models
2  
-from django.utils.encoding import python_2_unicode_compatible
3 2
 
4 3
 
5  
-@python_2_unicode_compatible
6 4
 class Comment(models.Model):
7 5
     pass
8 6
 
9 7
 
10  
-@python_2_unicode_compatible
11 8
 class Book(models.Model):
12 9
     title = models.CharField(max_length=100, db_index=True)
13 10
     comments = models.ManyToManyField(Comment)
8  tests/str/models.py
@@ -28,14 +28,6 @@ def __str__(self):
28 28
         return self.headline
29 29
 
30 30
 @python_2_unicode_compatible
31  
-class BrokenArticle(models.Model):
32  
-    headline = models.CharField(max_length=100)
33  
-    pub_date = models.DateTimeField()
34  
-
35  
-    def __unicode__(self):      # instead of __str__
36  
-        return self.headline
37  
-
38  
-@python_2_unicode_compatible
39 31
 class InternationalArticle(models.Model):
40 32
     headline = models.CharField(max_length=100)
41 33
     pub_date = models.DateTimeField()
12  tests/str/tests.py
@@ -7,7 +7,7 @@
7 7
 from django.utils import six
8 8
 from django.utils.unittest import skipIf
9 9
 
10  
-from .models import Article, BrokenArticle, InternationalArticle
  10
+from .models import Article, InternationalArticle
11 11
 
12 12
 
13 13
 class SimpleTests(TestCase):
@@ -21,16 +21,6 @@ def test_basic(self):
21 21
         self.assertEqual(str(a), str('Area man programs in Python'))
22 22
         self.assertEqual(repr(a), str('<Article: Area man programs in Python>'))
23 23
 
24  
-    @skipIf(six.PY3, "tests Model's default __str__ method under Python 2")
25  
-    def test_broken(self):
26  
-        # Regression test for #19362.
27  
-        a = BrokenArticle.objects.create(
28  
-            headline='Girl wins €12.500 in lottery',
29  
-            pub_date=datetime.datetime(2005, 7, 28)
30  
-        )
31  
-        six.assertRaisesRegex(self, RuntimeError, "Did you apply "
32  
-            "@python_2_unicode_compatible without defining __str__\?", str, a)
33  
-
34 24
     def test_international(self):
35 25
         a = InternationalArticle.objects.create(
36 26
             headline='Girl wins €12.500 in lottery',
10  tests/utils_tests/test_encoding.py
@@ -2,7 +2,8 @@
2 2
 from __future__ import unicode_literals
3 3
 
4 4
 from django.utils import unittest
5  
-from django.utils.encoding import force_bytes, filepath_to_uri
  5
+from django.utils.encoding import force_bytes, filepath_to_uri, python_2_unicode_compatible
  6
+from django.utils import six
6 7
 
7 8
 
8 9
 class TestEncodingUtils(unittest.TestCase):
@@ -21,3 +22,10 @@ def test_filepath_to_uri(self):
21 22
             'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4')
22 23
         self.assertEqual(filepath_to_uri('upload\\чубака.mp4'.encode('utf-8')),
23 24
             'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4')
  25
+
  26
+    @unittest.skipIf(six.PY3, "tests a class not defining __str__ under Python 2")
  27
+    def test_decorated_class_without_str(self):
  28
+        with self.assertRaises(ValueError):
  29
+            @python_2_unicode_compatible
  30
+            class NoStr(object):
  31
+                pass

0 notes on commit f0c7649

Please sign in to comment.
Something went wrong with that request. Please try again.