123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- # -*- coding: utf-8 -*-
- # Part of Odoo. See LICENSE file for full copyright and licensing details.
- import sys
- LOG_NOTSET = 'notset'
- LOG_DEBUG = 'debug'
- LOG_INFO = 'info'
- LOG_WARNING = 'warn'
- LOG_ERROR = 'error'
- LOG_CRITICAL = 'critical'
- # TODO get_encodings, ustr and exception_to_unicode were originally from tools.misc.
- # There are here until we refactor tools so that this module doesn't depends on tools.
- def get_encodings(hint_encoding='utf-8'):
- fallbacks = {
- 'latin1': 'latin9',
- 'iso-8859-1': 'iso8859-15',
- 'iso-8859-8-i': 'iso8859-8',
- 'cp1252': '1252',
- }
- if hint_encoding:
- yield hint_encoding
- if hint_encoding.lower() in fallbacks:
- yield fallbacks[hint_encoding.lower()]
- # some defaults (also taking care of pure ASCII)
- for charset in ['utf8','latin1']:
- if not hint_encoding or (charset.lower() != hint_encoding.lower()):
- yield charset
- from locale import getpreferredencoding
- prefenc = getpreferredencoding()
- if prefenc and prefenc.lower() != 'utf-8':
- yield prefenc
- prefenc = fallbacks.get(prefenc.lower())
- if prefenc:
- yield prefenc
- # not using pycompat to avoid circular import: pycompat is in tools much of
- # which comes back to import loglevels
- text_type = type(u'')
- def ustr(value, hint_encoding='utf-8', errors='strict'):
- """This method is similar to the builtin `unicode`, except
- that it may try multiple encodings to find one that works
- for decoding `value`, and defaults to 'utf-8' first.
- :param value: the value to convert
- :param hint_encoding: an optional encoding that was detected
- upstream and should be tried first to decode ``value``.
- :param str errors: optional `errors` flag to pass to the unicode
- built-in to indicate how illegal character values should be
- treated when converting a string: 'strict', 'ignore' or 'replace'
- (see ``unicode()`` constructor).
- Passing anything other than 'strict' means that the first
- encoding tried will be used, even if it's not the correct
- one to use, so be careful! Ignored if value is not a string/unicode.
- :raise: UnicodeError if value cannot be coerced to unicode
- :return: unicode string representing the given value
- """
- # We use direct type comparison instead of `isinstance`
- # as much as possible, in order to make the most common
- # cases faster (isinstance/issubclass are significantly slower)
- ttype = type(value)
- if ttype is text_type:
- return value
- # special short-circuit for str, as we still needs to support
- # str subclasses such as `odoo.tools.unquote`
- if ttype is bytes or issubclass(ttype, bytes):
- # try hint_encoding first, avoids call to get_encoding()
- # for the most common case
- try:
- return value.decode(hint_encoding, errors=errors)
- except Exception:
- pass
- # rare: no luck with hint_encoding, attempt other ones
- for ln in get_encodings(hint_encoding):
- try:
- return value.decode(ln, errors=errors)
- except Exception:
- pass
- if isinstance(value, Exception):
- return exception_to_unicode(value)
- # fallback for non-string values
- try:
- return text_type(value)
- except Exception:
- raise UnicodeError('unable to convert %r' % (value,))
- def exception_to_unicode(e):
- if getattr(e, 'args', ()):
- return "\n".join((ustr(a) for a in e.args))
- try:
- return text_type(e)
- except Exception:
- return u"Unknown message"
|