Fix exception_to_unicode() for oslo_i18n Message

Message instances created by oslo_i18n are subclasses of the Unicode
type (unicode on Python 2, str on Python 3) and have no __unicode__()
method. exception_to_unicode() raises an AttributeError when trying to
convert it to Unicode.

This change fixes this issue and adds an unit test.

Change-Id: Ica67429ac64f74e5c636b6d74d71910a26511378
This commit is contained in:
Victor Stinner 2015-07-02 17:16:14 +02:00
parent e94d1ccaf8
commit ac308341f6
2 changed files with 22 additions and 5 deletions

View File

@ -107,13 +107,23 @@ def exception_to_unicode(exc):
""" """
msg = None msg = None
if six.PY2: if six.PY2:
# Don't call directly unicode(exc), because it fails with # First try by calling the unicode type constructor. We should try
# UnicodeDecodeError on Python 2 if exc.__unicode__() returns a bytes # unicode() before exc.__unicode__() because subclasses of unicode can
# string not decodable from the default encoding (ASCII) # be easily casted to unicode, whereas they have no __unicode__()
# method.
try: try:
msg = exc.__unicode__() msg = unicode(exc)
except UnicodeError: except UnicodeError:
pass # unicode(exc) fail with UnicodeDecodeError on Python 2 if
# exc.__unicode__() or exc.__str__() returns a bytes string not
# decodable from the default encoding (ASCII)
if hasattr(exc, '__unicode__'):
# Call directly the __unicode__() method to avoid
# the implicit decoding from the default encoding
try:
msg = exc.__unicode__()
except UnicodeError:
pass
if msg is None: if msg is None:
# Don't call directly str(exc), because it fails with # Don't call directly str(exc), because it fails with

View File

@ -20,6 +20,7 @@ from oslotest import base as test_base
import six import six
import testtools import testtools
import oslo_i18n.fixture
from oslo_utils import encodeutils from oslo_utils import encodeutils
@ -231,3 +232,9 @@ class ExceptionToUnicodeTest(test_base.BaseTestCase):
exc = UnicodeOnlyException(b'utf-8 \xc3\xa9\xe2\x82\xac') exc = UnicodeOnlyException(b'utf-8 \xc3\xa9\xe2\x82\xac')
self.assertEqual(encodeutils.exception_to_unicode(exc), self.assertEqual(encodeutils.exception_to_unicode(exc),
u'utf-8 \xe9\u20ac') u'utf-8 \xe9\u20ac')
def test_oslo_i18n_message(self):
# use the lazy translation to get a Message instance of oslo_i18n
exc = oslo_i18n.fixture.Translation().lazy("test")
self.assertEqual(encodeutils.exception_to_unicode(exc),
u"test")