1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

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.
This commit is contained in:
Aymeric Augustin 2013-10-13 18:06:58 +02:00
parent 570d9c2678
commit 589dc49e12
6 changed files with 14 additions and 28 deletions

View File

@ -450,11 +450,6 @@ class Model(six.with_metaclass(ModelBase)):
def __str__(self): def __str__(self):
if six.PY2 and hasattr(self, '__unicode__'): 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 force_text(self).encode('utf-8')
return '%s object' % self.__class__.__name__ return '%s object' % self.__class__.__name__

View File

@ -28,6 +28,10 @@ def python_2_unicode_compatible(klass):
returning text and apply this decorator to the class. returning text and apply this decorator to the class.
""" """
if six.PY2: 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.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8') klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass return klass

View File

@ -1,13 +1,10 @@
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Comment(models.Model): class Comment(models.Model):
pass pass
@python_2_unicode_compatible
class Book(models.Model): class Book(models.Model):
title = models.CharField(max_length=100, db_index=True) title = models.CharField(max_length=100, db_index=True)
comments = models.ManyToManyField(Comment) comments = models.ManyToManyField(Comment)

View File

@ -27,14 +27,6 @@ class Article(models.Model):
# in ASCII. # in ASCII.
return self.headline 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 @python_2_unicode_compatible
class InternationalArticle(models.Model): class InternationalArticle(models.Model):
headline = models.CharField(max_length=100) headline = models.CharField(max_length=100)

View File

@ -7,7 +7,7 @@ from unittest import skipIf
from django.test import TestCase from django.test import TestCase
from django.utils import six from django.utils import six
from .models import Article, BrokenArticle, InternationalArticle from .models import Article, InternationalArticle
class SimpleTests(TestCase): class SimpleTests(TestCase):
@ -21,16 +21,6 @@ class SimpleTests(TestCase):
self.assertEqual(str(a), str('Area man programs in Python')) self.assertEqual(str(a), str('Area man programs in Python'))
self.assertEqual(repr(a), str('<Article: 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): def test_international(self):
a = InternationalArticle.objects.create( a = InternationalArticle.objects.create(
headline='Girl wins €12.500 in lottery', headline='Girl wins €12.500 in lottery',

View File

@ -5,7 +5,8 @@ import unittest
import datetime import datetime
from django.utils import six from django.utils import six
from django.utils.encoding import force_bytes, force_text, filepath_to_uri from django.utils.encoding import (force_bytes, force_text, filepath_to_uri,
python_2_unicode_compatible)
class TestEncodingUtils(unittest.TestCase): class TestEncodingUtils(unittest.TestCase):
@ -43,3 +44,10 @@ class TestEncodingUtils(unittest.TestCase):
'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4') 'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4')
self.assertEqual(filepath_to_uri('upload\\чубака.mp4'.encode('utf-8')), self.assertEqual(filepath_to_uri('upload\\чубака.mp4'.encode('utf-8')),
'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4') '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