Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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 authored February 28, 2010
11  django/utils/encoding.py
@@ -89,7 +89,16 @@ def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
89 89
             # SafeUnicode at the end.
90 90
             s = s.decode(encoding, errors)
91 91
     except UnicodeDecodeError, e:
92  
-        raise DjangoUnicodeDecodeError(s, *e.args)
  92
+        if not isinstance(s, Exception):
  93
+            raise DjangoUnicodeDecodeError(s, *e.args)
  94
+        else:
  95
+            # If we get to here, the caller has passed in an Exception
  96
+            # subclass populated with non-ASCII bytestring data without a
  97
+            # working unicode method. Try to handle this without raising a
  98
+            # further exception by individually forcing the exception args
  99
+            # to unicode.
  100
+            s = ' '.join([force_unicode(arg, encoding, strings_only,
  101
+                    errors) for arg in s])
93 102
     return s
94 103
 
95 104
 def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
10  tests/regressiontests/debug/__init__.py
... ...
@@ -0,0 +1,10 @@
  1
+# -*- coding: utf8 -*-
  2
+
  3
+class BrokenException(Exception):
  4
+    pass
  5
+
  6
+except_args = ('Broken!',           # plain exception with ASCII text
  7
+               u'¡Broken!',        # non-ASCII unicode data
  8
+               '¡Broken!',         # non-ASCII, utf-8 encoded bytestring
  9
+               '\xa1Broken!', )     # non-ASCII, latin1 bytestring
  10
+
0  tests/regressiontests/debug/models.py
No changes.
21  tests/regressiontests/debug/tests.py
... ...
@@ -0,0 +1,21 @@
  1
+from django.test import TestCase
  2
+from django.conf import settings
  3
+from django.core.urlresolvers import reverse
  4
+
  5
+from regressiontests.debug import BrokenException, except_args
  6
+
  7
+class ExceptionTest(TestCase):
  8
+    urls = 'regressiontests.debug.urls'
  9
+
  10
+    def setUp(self):
  11
+        self.old_debug = settings.DEBUG
  12
+        settings.DEBUG = True
  13
+
  14
+    def tearDown(self):
  15
+        settings.DEBUG = self.old_debug
  16
+
  17
+    def test_view_exceptions(self):
  18
+        for n in range(len(except_args)):
  19
+            self.assertRaises(BrokenException, self.client.get,
  20
+                reverse('view_exception', args=(n,)))
  21
+
5  tests/regressiontests/debug/urls.py
... ...
@@ -0,0 +1,5 @@
  1
+from django.conf.urls.defaults import *
  2
+
  3
+urlpatterns = patterns('regressiontests.debug.views',
  4
+    url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
  5
+)
5  tests/regressiontests/debug/views.py
... ...
@@ -0,0 +1,5 @@
  1
+from regressiontests.debug import BrokenException, except_args
  2
+
  3
+def view_exception(request, n):
  4
+    raise BrokenException(except_args[int(n)])
  5
+

0 notes on commit 9e95d6f

Please sign in to comment.
Something went wrong with that request. Please try again.