Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #12302: Modified force_unicode to avoid raising unicode errors …

…when

handed exceptions with non-ASCII bytestring data and no working unicode method
under Python 2.6 and higher.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@12621 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 9e95d6f6047a43268d3138a03342ad0534c4362b 1 parent 68f216a
Karen Tracey kmtracey authored
11 django/utils/encoding.py
View
@@ -89,7 +89,16 @@ def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
# SafeUnicode at the end.
s = s.decode(encoding, errors)
except UnicodeDecodeError, e:
- raise DjangoUnicodeDecodeError(s, *e.args)
+ if not isinstance(s, Exception):
+ raise DjangoUnicodeDecodeError(s, *e.args)
+ else:
+ # If we get to here, the caller has passed in an Exception
+ # subclass populated with non-ASCII bytestring data without a
+ # working unicode method. Try to handle this without raising a
+ # further exception by individually forcing the exception args
+ # to unicode.
+ s = ' '.join([force_unicode(arg, encoding, strings_only,
+ errors) for arg in s])
return s
def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
10 tests/regressiontests/debug/__init__.py
View
@@ -0,0 +1,10 @@
+# -*- coding: utf8 -*-
+
+class BrokenException(Exception):
+ pass
+
+except_args = ('Broken!', # plain exception with ASCII text
+ u'¡Broken!', # non-ASCII unicode data
+ '¡Broken!', # non-ASCII, utf-8 encoded bytestring
+ '\xa1Broken!', ) # non-ASCII, latin1 bytestring
+
0  tests/regressiontests/debug/models.py
View
No changes.
21 tests/regressiontests/debug/tests.py
View
@@ -0,0 +1,21 @@
+from django.test import TestCase
+from django.conf import settings
+from django.core.urlresolvers import reverse
+
+from regressiontests.debug import BrokenException, except_args
+
+class ExceptionTest(TestCase):
+ urls = 'regressiontests.debug.urls'
+
+ def setUp(self):
+ self.old_debug = settings.DEBUG
+ settings.DEBUG = True
+
+ def tearDown(self):
+ settings.DEBUG = self.old_debug
+
+ def test_view_exceptions(self):
+ for n in range(len(except_args)):
+ self.assertRaises(BrokenException, self.client.get,
+ reverse('view_exception', args=(n,)))
+
5 tests/regressiontests/debug/urls.py
View
@@ -0,0 +1,5 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('regressiontests.debug.views',
+ url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
+)
5 tests/regressiontests/debug/views.py
View
@@ -0,0 +1,5 @@
+from regressiontests.debug import BrokenException, except_args
+
+def view_exception(request, n):
+ raise BrokenException(except_args[int(n)])
+
Please sign in to comment.
Something went wrong with that request. Please try again.