From 7bf401381db1ba2bbed032e394d9ae8a11fb180b Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 26 Jan 2011 15:22:19 +0100 Subject: [PATCH] [IMP] netsvc/tools.config: the part of netsvc tools.config needs is moved in a new loglevels module. bzr revid: vmt@openerp.com-20110126142219-18j842m60diwsdph --- bin/loglevels.py | 172 ++++++++++++++++++++++++++++++++++++++++++++ bin/netsvc.py | 84 +--------------------- bin/tools/config.py | 4 +- 3 files changed, 177 insertions(+), 83 deletions(-) create mode 100644 bin/loglevels.py diff --git a/bin/loglevels.py b/bin/loglevels.py new file mode 100644 index 00000000000..1b41714c3b8 --- /dev/null +++ b/bin/loglevels.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import logging +import warnings + +LOG_NOTSET = 'notset' +LOG_DEBUG_SQL = 'debug_sql' +LOG_DEBUG_RPC_ANSWER = 'debug_rpc_answer' +LOG_DEBUG_RPC = 'debug_rpc' +LOG_DEBUG = 'debug' +LOG_TEST = 'test' +LOG_INFO = 'info' +LOG_WARNING = 'warn' +LOG_ERROR = 'error' +LOG_CRITICAL = 'critical' + +logging.DEBUG_RPC_ANSWER = logging.DEBUG - 4 +logging.addLevelName(logging.DEBUG_RPC_ANSWER, 'DEBUG_RPC_ANSWER') +logging.DEBUG_RPC = logging.DEBUG - 2 +logging.addLevelName(logging.DEBUG_RPC, 'DEBUG_RPC') +logging.DEBUG_SQL = logging.DEBUG_RPC - 3 +logging.addLevelName(logging.DEBUG_SQL, 'DEBUG_SQL') + +logging.TEST = logging.INFO - 5 +logging.addLevelName(logging.TEST, 'TEST') + +class Logger(object): + def __init__(self): + warnings.warn("The netsvc.Logger API shouldn't be used anymore, please " + "use the standard `logging.getLogger` API instead", + PendingDeprecationWarning, stacklevel=2) + super(Logger, self).__init__() + + def notifyChannel(self, name, level, msg): + warnings.warn("notifyChannel API shouldn't be used anymore, please use " + "the standard `logging` module instead", + PendingDeprecationWarning, stacklevel=2) + from service.web_services import common + + log = logging.getLogger(ustr(name)) + + if level in [LOG_DEBUG_RPC, LOG_TEST] and not hasattr(log, level): + fct = lambda msg, *args, **kwargs: log.log(getattr(logging, level.upper()), msg, *args, **kwargs) + setattr(log, level, fct) + + + level_method = getattr(log, level) + + if isinstance(msg, Exception): + msg = exception_to_unicode(msg) + + try: + msg = ustr(msg).strip() + if level in (LOG_ERROR, LOG_CRITICAL): # and tools.config.get_misc('debug','env_info',False): + msg = common().exp_get_server_environment() + "\n" + msg + + result = msg.split('\n') + except UnicodeDecodeError: + result = msg.strip().split('\n') + try: + if len(result)>1: + for idx, s in enumerate(result): + level_method('[%02d]: %s' % (idx+1, s,)) + elif result: + level_method(result[0]) + except IOError: + # TODO: perhaps reset the logger streams? + #if logrotate closes our files, we end up here.. + pass + except Exception: + # better ignore the exception and carry on.. + pass + + def set_loglevel(self, level, logger=None): + if logger is not None: + log = logging.getLogger(str(logger)) + else: + log = logging.getLogger() + log.setLevel(logging.INFO) # make sure next msg is printed + log.info("Log level changed to %s" % logging.getLevelName(level)) + log.setLevel(level) + + def shutdown(self): + logging.shutdown() + +# TODO get_encodings, ustr and exception_to_unicode are taken from tools.misc +# but we don't want to depend on tools. + +def get_encodings(hint_encoding='utf-8'): + fallbacks = { + 'latin1': 'latin9', + 'iso-8859-1': 'iso8859-15', + '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 + +def ustr(value, hint_encoding='utf-8'): + """This method is similar to the builtin `str` method, except + it will return unicode() string. + + @param value: the value to convert + @param hint_encoding: an optional encoding that was detected + upstream and should be tried first to + decode ``value``. + + @rtype: unicode + @return: unicode string + """ + if isinstance(value, Exception): + return exception_to_unicode(value) + + if isinstance(value, unicode): + return value + + if not isinstance(value, basestring): + try: + return unicode(value) + except Exception: + raise UnicodeError('unable to convert %r' % (value,)) + + for ln in get_encodings(hint_encoding): + try: + return unicode(value, ln) + except Exception: + pass + raise UnicodeError('unable to convert %r' % (value,)) + + +def exception_to_unicode(e): + if (sys.version_info[:2] < (2,6)) and hasattr(e, 'message'): + return ustr(e.message) + if hasattr(e, 'args'): + return "\n".join((ustr(a) for a in e.args)) + try: + return ustr(e) + except Exception: + return u"Unknown message" diff --git a/bin/netsvc.py b/bin/netsvc.py index c2360ae5ee7..f79aab382b9 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -37,6 +37,9 @@ from pprint import pformat import warnings import heapq +# TODO modules that import netsvc only for things from loglevels must be changed to use loglevels. +from loglevels import * + class Service(object): """ Base class for *Local* services @@ -130,27 +133,6 @@ class ExportService(object): else: raise -LOG_NOTSET = 'notset' -LOG_DEBUG_SQL = 'debug_sql' -LOG_DEBUG_RPC_ANSWER = 'debug_rpc_answer' -LOG_DEBUG_RPC = 'debug_rpc' -LOG_DEBUG = 'debug' -LOG_TEST = 'test' -LOG_INFO = 'info' -LOG_WARNING = 'warn' -LOG_ERROR = 'error' -LOG_CRITICAL = 'critical' - -logging.DEBUG_RPC_ANSWER = logging.DEBUG - 4 -logging.addLevelName(logging.DEBUG_RPC_ANSWER, 'DEBUG_RPC_ANSWER') -logging.DEBUG_RPC = logging.DEBUG - 2 -logging.addLevelName(logging.DEBUG_RPC, 'DEBUG_RPC') -logging.DEBUG_SQL = logging.DEBUG_RPC - 3 -logging.addLevelName(logging.DEBUG_SQL, 'DEBUG_SQL') - -logging.TEST = logging.INFO - 5 -logging.addLevelName(logging.TEST, 'TEST') - BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, _NOTHING, DEFAULT = range(10) #The background is set with 40 plus the number of the color, and the foreground with 30 #These are the sequences need to get colored ouput @@ -229,66 +211,6 @@ def init_logger(): logger.addHandler(handler) logger.setLevel(int(tools.config['log_level'] or '0')) - -class Logger(object): - def __init__(self): - warnings.warn("The netsvc.Logger API shouldn't be used anymore, please " - "use the standard `logging.getLogger` API instead", - PendingDeprecationWarning, stacklevel=2) - super(Logger, self).__init__() - - def notifyChannel(self, name, level, msg): - warnings.warn("notifyChannel API shouldn't be used anymore, please use " - "the standard `logging` module instead", - PendingDeprecationWarning, stacklevel=2) - from service.web_services import common - - log = logging.getLogger(tools.ustr(name)) - - if level in [LOG_DEBUG_RPC, LOG_TEST] and not hasattr(log, level): - fct = lambda msg, *args, **kwargs: log.log(getattr(logging, level.upper()), msg, *args, **kwargs) - setattr(log, level, fct) - - - level_method = getattr(log, level) - - if isinstance(msg, Exception): - msg = tools.exception_to_unicode(msg) - - try: - msg = tools.ustr(msg).strip() - if level in (LOG_ERROR, LOG_CRITICAL) and tools.config.get_misc('debug','env_info',False): - msg = common().exp_get_server_environment() + "\n" + msg - - result = msg.split('\n') - except UnicodeDecodeError: - result = msg.strip().split('\n') - try: - if len(result)>1: - for idx, s in enumerate(result): - level_method('[%02d]: %s' % (idx+1, s,)) - elif result: - level_method(result[0]) - except IOError: - # TODO: perhaps reset the logger streams? - #if logrotate closes our files, we end up here.. - pass - except Exception: - # better ignore the exception and carry on.. - pass - - def set_loglevel(self, level, logger=None): - if logger is not None: - log = logging.getLogger(str(logger)) - else: - log = logging.getLogger() - log.setLevel(logging.INFO) # make sure next msg is printed - log.info("Log level changed to %s" % logging.getLevelName(level)) - log.setLevel(level) - - def shutdown(self): - logging.shutdown() - import tools init_logger() diff --git a/bin/tools/config.py b/bin/tools/config.py index bc9229e0b72..b7ebd1d26a6 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -23,7 +23,7 @@ import ConfigParser import optparse import os import sys -import netsvc +import loglevels import logging import release @@ -102,7 +102,7 @@ class configmanager(object): self.config_file = fname self.has_ssl = check_ssl() - self._LOGLEVELS = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) + self._LOGLEVELS = dict([(getattr(loglevels, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'TEST', 'DEBUG', 'DEBUG_RPC', 'DEBUG_SQL', 'DEBUG_RPC_ANSWER','NOTSET')]) version = "%s %s" % (release.description, release.version)