diff --git a/powerline/__init__.py b/powerline/__init__.py index 4df195dd..c82163a9 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -7,46 +7,14 @@ import logging from powerline.colorscheme import Colorscheme from powerline.lib.config import ConfigLoader +from powerline.lib.unicode import safe_unicode, FailedUnicode 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. - - 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: @@ -69,7 +37,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..a1a5d567 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,48 @@ 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) + + +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