summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2013-10-13 18:06:58 +0200
committerAymeric Augustin <aymeric.augustin@m4x.org>2013-10-13 18:25:21 +0200
commitf0c7649b1692f8441eb9b9b923b2bed8e95f9185 (patch)
tree8ee531e9ad078dd525f2364ca1b3d55233eb217b
parentddff6522fa72aacc7475ba5cd4bf8683ff12b8c7 (diff)
Fixed #21198 -- Prevented invalid use of @python_2_unicode_compatible.
Thanks jpic for the report and chmodas for working on a patch. Reverts 2ea80b94. Refs #19362. Conflicts: tests/utils_tests/test_encoding.py
-rw-r--r--django/db/models/base.py5
-rw-r--r--django/utils/encoding.py4
-rw-r--r--tests/commands_sql/models.py3
-rw-r--r--tests/str/models.py8
-rw-r--r--tests/str/tests.py12
-rw-r--r--tests/utils_tests/test_encoding.py10
6 files changed, 14 insertions, 28 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 33229f21f3..f6001b4e93 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -427,11 +427,6 @@ class Model(six.with_metaclass(ModelBase)):
def __str__(self):
if six.PY2 and hasattr(self, '__unicode__'):
- if type(self).__unicode__ == Model.__str__:
- klass_name = type(self).__name__
- raise RuntimeError("%s.__unicode__ is aliased to __str__. Did"
- " you apply @python_2_unicode_compatible"
- " without defining __str__?" % klass_name)
return force_text(self).encode('utf-8')
return '%s object' % self.__class__.__name__
diff --git a/django/utils/encoding.py b/django/utils/encoding.py
index ad06336c4d..599952bdeb 100644
--- a/django/utils/encoding.py
+++ b/django/utils/encoding.py
@@ -52,6 +52,10 @@ def python_2_unicode_compatible(klass):
returning text and apply this decorator to the class.
"""
if six.PY2:
+ if '__str__' not in klass.__dict__:
+ raise ValueError("@python_2_unicode_compatible cannot be applied "
+ "to %s because it doesn't define __str__()." %
+ klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass
diff --git a/tests/commands_sql/models.py b/tests/commands_sql/models.py
index d8f372b403..78ad722307 100644
--- a/tests/commands_sql/models.py
+++ b/tests/commands_sql/models.py
@@ -1,13 +1,10 @@
from django.db import models
-from django.utils.encoding import python_2_unicode_compatible
-@python_2_unicode_compatible
class Comment(models.Model):
pass
-@python_2_unicode_compatible
class Book(models.Model):
title = models.CharField(max_length=100, db_index=True)
comments = models.ManyToManyField(Comment)
diff --git a/tests/str/models.py b/tests/str/models.py
index 1c158ea008..488012e861 100644
--- a/tests/str/models.py
+++ b/tests/str/models.py
@@ -28,14 +28,6 @@ class Article(models.Model):
return self.headline
@python_2_unicode_compatible
-class BrokenArticle(models.Model):
- headline = models.CharField(max_length=100)
- pub_date = models.DateTimeField()
-
- def __unicode__(self): # instead of __str__
- return self.headline
-
-@python_2_unicode_compatible
class InternationalArticle(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateTimeField()
diff --git a/tests/str/tests.py b/tests/str/tests.py
index bd85c48d05..2c11ac8c78 100644
--- a/tests/str/tests.py
+++ b/tests/str/tests.py
@@ -7,7 +7,7 @@ from django.test import TestCase
from django.utils import six
from django.utils.unittest import skipIf
-from .models import Article, BrokenArticle, InternationalArticle
+from .models import Article, InternationalArticle
class SimpleTests(TestCase):
@@ -21,16 +21,6 @@ class SimpleTests(TestCase):
self.assertEqual(str(a), str('Area man programs in Python'))
self.assertEqual(repr(a), str('<Article: Area man programs in Python>'))
- @skipIf(six.PY3, "tests Model's default __str__ method under Python 2")
- def test_broken(self):
- # Regression test for #19362.
- a = BrokenArticle.objects.create(
- headline='Girl wins €12.500 in lottery',
- pub_date=datetime.datetime(2005, 7, 28)
- )
- six.assertRaisesRegex(self, RuntimeError, "Did you apply "
- "@python_2_unicode_compatible without defining __str__\?", str, a)
-
def test_international(self):
a = InternationalArticle.objects.create(
headline='Girl wins €12.500 in lottery',
diff --git a/tests/utils_tests/test_encoding.py b/tests/utils_tests/test_encoding.py
index 7aaba25a7a..df4ea1497a 100644
--- a/tests/utils_tests/test_encoding.py
+++ b/tests/utils_tests/test_encoding.py
@@ -2,7 +2,8 @@
from __future__ import unicode_literals
from django.utils import unittest
-from django.utils.encoding import force_bytes, filepath_to_uri
+from django.utils.encoding import force_bytes, filepath_to_uri, python_2_unicode_compatible
+from django.utils import six
class TestEncodingUtils(unittest.TestCase):
@@ -21,3 +22,10 @@ class TestEncodingUtils(unittest.TestCase):
'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4')
self.assertEqual(filepath_to_uri('upload\\чубака.mp4'.encode('utf-8')),
'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4')
+
+ @unittest.skipIf(six.PY3, "tests a class not defining __str__ under Python 2")
+ def test_decorated_class_without_str(self):
+ with self.assertRaises(ValueError):
+ @python_2_unicode_compatible
+ class NoStr(object):
+ pass