[Kimchi-devel] [PATCH] kimchi.exception: Properly Decode All Kinds of Exception Arguments

zhshzhou at linux.vnet.ibm.com zhshzhou at linux.vnet.ibm.com
Wed Apr 2 05:42:34 UTC 2014


From: Zhou Zheng Sheng <zhshzhou at linux.vnet.ibm.com>

KimchiException provides the ability to translate each argument and the
error message. It decodes the translated message to unicode. It's also
smart and avoids decoding a unicode argument twice by a check to make
sure the to-be-decoded value is not unicode.

The problem is that when a KimchiException is initialized by another
KimchiException, for example,

try:
    ...
except OperationFailed as e:
    ...
    raise OperationFailed('KCHXXXX', {'err': e})

the variable "e" is not a unicode object so it passes the check
mentioned above, then it gets decoded twice and raises an encoding
exception.

This patch does not only rely on the type of the to-be-decoded object,
but also catches the encoding exeption. It firstly try to call str(obj)
to get the ascii string of the obj, then decodes it to unicode. This is
valid for a normal string or any object can format itself to a normal
string. If it fails, it try to call unicode(obj) to get the unicode
string of the object. This is valid for objects can format themselves
to a unicode string. In all, it handles various objects like following.

If obj is a unicode string, use it directly.
If obj is a normal string, decode it to a unicode string.
If obj can format itself to a normal string, format it and decode it to
unicode.
If obj can format itself to a unicode string, format it.

Another problem is that by the current design, KimchiException always
stores error message in unicode. This can cause encoding exception when
we call "str(KimchiExceptionObject)". This patch is not a total refactor
of the translation and encoding so it does not solve this problem. The
workaround is using KimchiExceptionObject.message instead of str it.

Notice: I'm following the Python str.encode and decode semantics in the
commit message.
"encode" means converting unicode sting to ascii/utf-8.
"decode" means converting ascii/utf-8 string to unicode.
"encoding" means the action of decode and encode in general.

Signed-off-by: Zhou Zheng Sheng <zhshzhou at linux.vnet.ibm.com>
---
 src/kimchi/asynctask.py | 2 +-
 src/kimchi/exception.py | 8 +++++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/kimchi/asynctask.py b/src/kimchi/asynctask.py
index 8f0d96c..54fb749 100644
--- a/src/kimchi/asynctask.py
+++ b/src/kimchi/asynctask.py
@@ -68,4 +68,4 @@ class AsyncTask(object):
         except Exception, e:
             cherrypy.log.error_log.error("Error in async_task %s " % self.id)
             cherrypy.log.error_log.error(traceback.format_exc())
-            cb("Unexpected exception: %s" % str(e), False)
+            cb("Unexpected exception: %s" % e.message, False)
diff --git a/src/kimchi/exception.py b/src/kimchi/exception.py
index 87982ea..fcf60cc 100644
--- a/src/kimchi/exception.py
+++ b/src/kimchi/exception.py
@@ -54,7 +54,13 @@ class KimchiException(Exception):
 
         for key, value in args.iteritems():
             if not isinstance(value, unicode):
-                args[key] = unicode(str(value), 'utf-8')
+                try:
+                    # In case the value formats itself to an ascii string.
+                    args[key] = unicode(str(value), 'utf-8')
+                except UnicodeEncodeError:
+                    # In case the value is a KimchiException or it formats
+                    # itself to a unicode string.
+                    args[key] = unicode(value)
 
         return unicode(translation.gettext(text), 'utf-8') % args
 
-- 
1.8.5.3




More information about the Kimchi-devel mailing list