[IMP] Rename menu Configuration to General Settings
[odoo/odoo.git] / openerp / loglevels.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import sys
23 import logging
24
25 LOG_NOTSET = 'notset'
26 LOG_DEBUG = 'debug'
27 LOG_TEST = 'test'
28 LOG_INFO = 'info'
29 LOG_WARNING = 'warn'
30 LOG_ERROR = 'error'
31 LOG_CRITICAL = 'critical'
32
33 logging.TEST = logging.INFO - 5
34 logging.addLevelName(logging.TEST, 'TEST')
35
36 _logger = logging.getLogger(__name__)
37
38 class Logger(object):
39     def __init__(self):
40         _logger.warning(
41             "The netsvc.Logger API shouldn't be used anymore, please "
42             "use the standard `logging.getLogger` API instead.")
43         super(Logger, self).__init__()
44
45     def notifyChannel(self, name, level, msg):
46         _logger.warning(
47             "notifyChannel API shouldn't be used anymore, please use "
48             "the standard `logging` module instead.")
49         from service.web_services import common
50
51         log = logging.getLogger(__name__ + '.deprecated.' + ustr(name))
52
53         if level in [LOG_TEST] and not hasattr(log, level):
54             fct = lambda msg, *args, **kwargs: log.log(getattr(logging, level.upper()), msg, *args, **kwargs)
55             setattr(log, level, fct)
56
57
58         level_method = getattr(log, level)
59
60         if isinstance(msg, Exception):
61             msg = exception_to_unicode(msg)
62
63         try:
64             msg = ustr(msg).strip()
65             if level in (LOG_ERROR, LOG_CRITICAL): # and tools.config.get_misc('debug','env_info',False):
66                 msg = common().exp_get_server_environment() + "\n" + msg
67
68             result = msg.split('\n')
69         except UnicodeDecodeError:
70             result = msg.strip().split('\n')
71         try:
72             if len(result)>1:
73                 for idx, s in enumerate(result):
74                     level_method('[%02d]: %s' % (idx+1, s,))
75             elif result:
76                 level_method(result[0])
77         except IOError:
78             # TODO: perhaps reset the logger streams?
79             #if logrotate closes our files, we end up here..
80             pass
81         except Exception:
82             # better ignore the exception and carry on..
83             pass
84
85     def set_loglevel(self, level, logger=None):
86         if logger is not None:
87             log = logging.getLogger(str(logger))
88         else:
89             log = logging.getLogger()
90         log.setLevel(logging.INFO) # make sure next msg is printed
91         log.info("Log level changed to %s" % logging.getLevelName(level))
92         log.setLevel(level)
93
94     def shutdown(self):
95         logging.shutdown()
96
97 # TODO get_encodings, ustr and exception_to_unicode were originally from tools.misc.
98 # There are here until we refactor tools so that this module doesn't depends on tools.
99
100 def get_encodings(hint_encoding='utf-8'):
101     fallbacks = {
102         'latin1': 'latin9',
103         'iso-8859-1': 'iso8859-15',
104         'cp1252': '1252',
105     }
106     if hint_encoding:
107         yield hint_encoding
108         if hint_encoding.lower() in fallbacks:
109             yield fallbacks[hint_encoding.lower()]
110
111     # some defaults (also taking care of pure ASCII)
112     for charset in ['utf8','latin1']:
113         if not (hint_encoding) or (charset.lower() != hint_encoding.lower()):
114             yield charset
115
116     from locale import getpreferredencoding
117     prefenc = getpreferredencoding()
118     if prefenc and prefenc.lower() != 'utf-8':
119         yield prefenc
120         prefenc = fallbacks.get(prefenc.lower())
121         if prefenc:
122             yield prefenc
123
124 def ustr(value, hint_encoding='utf-8', errors='strict'):
125     """This method is similar to the builtin `unicode`, except
126     that it may try multiple encodings to find one that works
127     for decoding `value`, and defaults to 'utf-8' first.
128
129     :param: value: the value to convert
130     :param: hint_encoding: an optional encoding that was detecte
131         upstream and should be tried first to decode ``value``.
132     :param str error: optional `errors` flag to pass to the unicode
133         built-in to indicate how illegal character values should be
134         treated when converting a string: 'strict', 'ignore' or 'replace'.
135         Passing anything other than 'strict' means that the first
136         encoding tried will be used, even if it's not the correct
137         one to use, so be careful! Ignore if value is not a string/unicode.
138     :rtype: unicode
139     :raise: UnicodeError if value cannot be coerced to unicode
140     """
141     if isinstance(value, Exception):
142         return exception_to_unicode(value)
143
144     if isinstance(value, unicode):
145         return value
146
147     if not isinstance(value, basestring):
148         try:
149             return unicode(value)
150         except Exception:
151             raise UnicodeError('unable to convert %r' % (value,))
152
153     for ln in get_encodings(hint_encoding):
154         try:
155             return unicode(value, ln, errors=errors)
156         except Exception:
157             pass
158     raise UnicodeError('unable to convert %r' % (value,))
159
160
161 def exception_to_unicode(e):
162     if (sys.version_info[:2] < (2,6)) and hasattr(e, 'message'):
163         return ustr(e.message)
164     if hasattr(e, 'args'):
165         return "\n".join((ustr(a) for a in e.args))
166     try:
167         return unicode(e)
168     except Exception:
169         return u"Unknown message"
170
171 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: