Coverage for adhoc-cicd-odoo-odoo / odoo / loglevels.py: 15%

49 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-09 18:22 +0000

1# -*- coding: utf-8 -*- 

2# Part of Odoo. See LICENSE file for full copyright and licensing details. 

3import contextlib 

4import warnings 

5 

6LOG_NOTSET = 'notset' 

7LOG_DEBUG = 'debug' 

8LOG_INFO = 'info' 

9LOG_WARNING = 'warn' 

10LOG_ERROR = 'error' 

11LOG_CRITICAL = 'critical' 

12 

13# TODO get_encodings, ustr and exception_to_unicode were originally from tools.misc. 

14# There are here until we refactor tools so that this module doesn't depends on tools. 

15 

16def get_encodings(hint_encoding='utf-8'): 

17 warnings.warn( 

18 "Deprecated since Odoo 18. Mostly nonsensical as the " 

19 "second/third encoding it yields is latin-1 which always succeeds...", 

20 stacklevel=2, 

21 category=DeprecationWarning, 

22 ) 

23 fallbacks = { 

24 'latin1': 'latin9', 

25 'iso-8859-1': 'iso8859-15', 

26 'iso-8859-8-i': 'iso8859-8', 

27 'cp1252': '1252', 

28 } 

29 if hint_encoding: 

30 yield hint_encoding 

31 if hint_encoding.lower() in fallbacks: 

32 yield fallbacks[hint_encoding.lower()] 

33 

34 # some defaults (also taking care of pure ASCII) 

35 for charset in ['utf8','latin1']: 

36 if not hint_encoding or (charset.lower() != hint_encoding.lower()): 

37 yield charset 

38 

39 from locale import getpreferredencoding 

40 prefenc = getpreferredencoding() 

41 if prefenc and prefenc.lower() != 'utf-8': 

42 yield prefenc 

43 prefenc = fallbacks.get(prefenc.lower()) 

44 if prefenc: 

45 yield prefenc 

46 

47def ustr(value, hint_encoding='utf-8', errors='strict'): 

48 """This method is similar to the builtin `unicode`, except 

49 that it may try multiple encodings to find one that works 

50 for decoding `value`, and defaults to 'utf-8' first. 

51 

52 :param value: the value to convert 

53 :param hint_encoding: an optional encoding that was detected 

54 upstream and should be tried first to decode ``value``. 

55 :param str errors: optional `errors` flag to pass to the unicode 

56 built-in to indicate how illegal character values should be 

57 treated when converting a string: 'strict', 'ignore' or 'replace' 

58 (see ``unicode()`` constructor). 

59 Passing anything other than 'strict' means that the first 

60 encoding tried will be used, even if it's not the correct 

61 one to use, so be careful! Ignored if value is not a string/unicode. 

62 :raise: UnicodeError if value cannot be coerced to unicode 

63 :return: unicode string representing the given value 

64 """ 

65 warnings.warn( 

66 "Deprecated since Odoo 18: ustr() is a garbage bag of weirdo fallbacks " 

67 "which mostly don't do anything as\n" 

68 "- the first attempt will always work if errors is not `strict`\n" 

69 "- if utf8 fails it moves on to latin-1 which always works\n" 

70 "- and it always tries hint-encoding twice", 

71 stacklevel=2, 

72 category=DeprecationWarning, 

73 ) 

74 # We use direct type comparison instead of `isinstance` 

75 # as much as possible, in order to make the most common 

76 # cases faster (isinstance/issubclass are significantly slower) 

77 ttype = type(value) 

78 

79 if ttype is str: 

80 return value 

81 

82 # special short-circuit for str, as we still needs to support 

83 # str subclasses such as `odoo.tools.unquote` 

84 if ttype is bytes or issubclass(ttype, bytes): 

85 

86 # try hint_encoding first, avoids call to get_encoding() 

87 # for the most common case 

88 with contextlib.suppress(Exception): 

89 return value.decode(hint_encoding, errors=errors) 

90 

91 # rare: no luck with hint_encoding, attempt other ones 

92 for ln in get_encodings(hint_encoding): 

93 with contextlib.suppress(Exception): 

94 return value.decode(ln, errors=errors) 

95 

96 if isinstance(value, Exception): 

97 return exception_to_unicode(value) 

98 

99 # fallback for non-string values 

100 try: 

101 return str(value) 

102 except Exception as e: 

103 raise UnicodeError(f'unable to convert {value!r}') from e 

104 

105 

106def exception_to_unicode(e): 

107 if getattr(e, 'args', ()): 

108 return "\n".join(map(str, e.args)) 

109 try: 

110 return str(e) 

111 except Exception: 

112 return "Unknown message"