mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +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:
		@@ -450,11 +450,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__
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -27,14 +27,6 @@ class Article(models.Model):
 | 
			
		||||
        # in ASCII.
 | 
			
		||||
        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)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ from unittest import skipIf
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
from django.utils import six
 | 
			
		||||
 | 
			
		||||
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',
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,8 @@ import unittest
 | 
			
		||||
import datetime
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
@@ -43,3 +44,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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user