From d8562256c1103fd218e98767b9b26f2a714d16d5 Mon Sep 17 00:00:00 2001 From: ZyX Date: Thu, 13 Mar 2014 23:41:25 +0400 Subject: [PATCH 1/2] Do not allow unicode-related exceptions inside logger Fixes #421 --- powerline/__init__.py | 23 ++--------------------- powerline/lib/unicode.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/powerline/__init__.py b/powerline/__init__.py index 4df195dd..465680d6 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -7,33 +7,14 @@ import logging from powerline.colorscheme import Colorscheme from powerline.lib.config import ConfigLoader +from powerline.lib.unicode import safe_unicode from threading import Lock, Event -try: - from __builtin__ import unicode -except ImportError: - unicode = str # NOQA - DEFAULT_SYSTEM_CONFIG_DIR = None -def safe_unicode(s): - '''Return unicode instance without raising an exception. - ''' - try: - try: - return unicode(s) - except UnicodeDecodeError: - try: - return unicode(s, 'utf-8') - except TypeError: - return unicode(str(s), 'utf-8') - except Exception as e: - return safe_unicode(e) - - class FailedUnicode(unicode): '''Builtin ``unicode`` (``str`` in python 3) subclass indicating fatal error. @@ -69,7 +50,7 @@ class PowerlineLogger(object): prefix = self.ext + ((':' + prefix) if prefix else '') if args or kwargs: msg = msg.format(*args, **kwargs) - msg = prefix + ':' + msg + msg = prefix + ':' + safe_unicode(msg) key = attr + ':' + prefix if msg != self.last_msgs.get(key): getattr(self.logger, attr)(msg) diff --git a/powerline/lib/unicode.py b/powerline/lib/unicode.py index 645d4d7b..aa717fee 100644 --- a/powerline/lib/unicode.py +++ b/powerline/lib/unicode.py @@ -1,5 +1,9 @@ # vim:fileencoding=utf-8:noet + +from locale import getpreferredencoding + + try: from __builtin__ import unicode except ImportError: @@ -7,7 +11,35 @@ except ImportError: def u(s): + '''Return unicode instance assuming UTF-8 encoded string. + ''' if type(s) is unicode: return s else: return unicode(s, 'utf-8') + + +def safe_unicode(s): + '''Return unicode instance without raising an exception. + + Order of assumptions: + * ASCII string or unicode object + * UTF-8 string + * Object with __str__() or __repr__() method that returns UTF-8 string or + unicode object (depending on python version) + * String in locale.getpreferredencoding() encoding + * If everything failed use safe_unicode on last exception with which + everything failed + ''' + try: + try: + return unicode(s) + except UnicodeDecodeError: + try: + return unicode(s, 'utf-8') + except TypeError: + return unicode(str(s), 'utf-8') + except UnicodeDecodeError: + return unicode(s, getpreferredencoding()) + except Exception as e: + return safe_unicode(e) From 839038d58e410aeea1721581aae765d4d035593b Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 15 Mar 2014 01:27:10 +0400 Subject: [PATCH 2/2] Also move FailedUnicode to powerline/lib/unicode --- powerline/__init__.py | 15 +-------------- powerline/lib/unicode.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/powerline/__init__.py b/powerline/__init__.py index 465680d6..c82163a9 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -7,7 +7,7 @@ import logging from powerline.colorscheme import Colorscheme from powerline.lib.config import ConfigLoader -from powerline.lib.unicode import safe_unicode +from powerline.lib.unicode import safe_unicode, FailedUnicode from threading import Lock, Event @@ -15,19 +15,6 @@ from threading import Lock, Event DEFAULT_SYSTEM_CONFIG_DIR = None -class FailedUnicode(unicode): - '''Builtin ``unicode`` (``str`` in python 3) subclass indicating fatal - error. - - If your code for some reason wants to determine whether `.render()` method - failed it should check returned string for being a FailedUnicode instance. - Alternatively you could subclass Powerline and override `.render()` method - to do what you like in place of catching the exception and returning - FailedUnicode. - ''' - pass - - def find_config_file(search_paths, config_file): config_file += '.json' for path in search_paths: diff --git a/powerline/lib/unicode.py b/powerline/lib/unicode.py index aa717fee..a1a5d567 100644 --- a/powerline/lib/unicode.py +++ b/powerline/lib/unicode.py @@ -43,3 +43,16 @@ def safe_unicode(s): return unicode(s, getpreferredencoding()) except Exception as e: return safe_unicode(e) + + +class FailedUnicode(unicode): + '''Builtin ``unicode`` (``str`` in python 3) subclass indicating fatal + error. + + If your code for some reason wants to determine whether `.render()` method + failed it should check returned string for being a FailedUnicode instance. + Alternatively you could subclass Powerline and override `.render()` method + to do what you like in place of catching the exception and returning + FailedUnicode. + ''' + pass