Skip to content

Commit

Permalink
Fixed #21198 -- Prevented invalid use of @python_2_unicode_compatible.
Browse files Browse the repository at this point in the history
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
aaugustin committed Oct 13, 2013
1 parent ddff652 commit f0c7649
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 28 deletions.
5 changes: 0 additions & 5 deletions django/db/models/base.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -427,11 +427,6 @@ def __repr__(self):


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__


Expand Down
4 changes: 4 additions & 0 deletions django/utils/encoding.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -52,6 +52,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
Expand Down
3 changes: 0 additions & 3 deletions tests/commands_sql/models.py
Original file line number Original file line Diff line number Diff line change
@@ -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)
8 changes: 0 additions & 8 deletions tests/str/models.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ def __str__(self):
# 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)
Expand Down
12 changes: 1 addition & 11 deletions tests/str/tests.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from django.utils import six from django.utils import six
from django.utils.unittest import skipIf from django.utils.unittest import skipIf


from .models import Article, BrokenArticle, InternationalArticle from .models import Article, InternationalArticle




class SimpleTests(TestCase): class SimpleTests(TestCase):
Expand All @@ -21,16 +21,6 @@ def test_basic(self):
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',
Expand Down
10 changes: 9 additions & 1 deletion tests/utils_tests/test_encoding.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals


from django.utils import unittest 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): class TestEncodingUtils(unittest.TestCase):
Expand All @@ -21,3 +22,10 @@ def test_filepath_to_uri(self):
'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

0 comments on commit f0c7649

Please sign in to comment.