document: fix regressions at storage and node_descriptor
[odoo/odoo.git] / bin / netsvc.py
index 11f7ca5..eae5382 100644 (file)
 #
 ##############################################################################
 
-import errno
 import logging
 import logging.handlers
-import os
-import socket
 import sys
 import threading
 import time
@@ -103,12 +100,10 @@ class ExportService(object):
     
     _services = {}
     _groups = {}
-    _logger = logging.getLogger('web-services')
     
     def __init__(self, name, audience=''):
         ExportService._services[name] = self
         self.__name = name
-        self._logger.debug("Registered an exported service: %s" % name)
 
     def joinGroup(self, name):
         ExportService._groups.setdefault(name, {})[self.__name] = self
@@ -130,7 +125,6 @@ class ExportService(object):
             raise
 
 LOG_NOTSET = 'notset'
-LOG_DEBUG_SQL = 'debug_sql'
 LOG_DEBUG_RPC = 'debug_rpc'
 LOG_DEBUG = 'debug'
 LOG_TEST = 'test'
@@ -141,57 +135,28 @@ LOG_CRITICAL = 'critical'
 
 logging.DEBUG_RPC = logging.DEBUG - 2
 logging.addLevelName(logging.DEBUG_RPC, 'DEBUG_RPC')
-logging.DEBUG_SQL = logging.DEBUG_RPC - 2
-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
-RESET_SEQ = "\033[0m"
-COLOR_SEQ = "\033[1;%dm"
-BOLD_SEQ = "\033[1m"
-COLOR_PATTERN = "%s%s%%s%s" % (COLOR_SEQ, COLOR_SEQ, RESET_SEQ)
-LEVEL_COLOR_MAPPING = {
-    logging.DEBUG_SQL: (WHITE, MAGENTA),
-    logging.DEBUG_RPC: (BLUE, WHITE),
-    logging.DEBUG: (BLUE, DEFAULT),
-    logging.INFO: (GREEN, DEFAULT),
-    logging.TEST: (WHITE, BLUE),
-    logging.WARNING: (YELLOW, DEFAULT),
-    logging.ERROR: (RED, DEFAULT),
-    logging.CRITICAL: (WHITE, RED),
-}
-
-class DBFormatter(logging.Formatter):
-    def format(self, record):
-        record.dbname = getattr(threading.current_thread(), 'dbname', '?')
-        return logging.Formatter.format(self, record)
-
-class ColoredFormatter(DBFormatter):
-    def format(self, record):
-        fg_color, bg_color = LEVEL_COLOR_MAPPING[record.levelno]
-        record.levelname = COLOR_PATTERN % (30 + fg_color, 40 + bg_color, record.levelname)
-        return DBFormatter.format(self, record)
-
 def init_logger():
     import os
     from tools.translate import resetlocale
     resetlocale()
 
+    logger = logging.getLogger()
     # create a format for log messages and dates
-    format = '[%(asctime)s][%(dbname)s] %(levelname)s:%(name)s:%(message)s'
+    formatter = logging.Formatter('[%(asctime)s] %(levelname)s:%(name)s:%(message)s')
 
     if tools.config['syslog']:
         # SysLog Handler
         if os.name == 'nt':
-            handler = logging.handlers.NTEventLogHandler("%s %s" % (release.description, release.version))
+            handler = logging.handlers.NTEventLogHandler("%s %s" %
+                                                         (release.description,
+                                                          release.version))
         else:
             handler = logging.handlers.SysLogHandler('/dev/log')
-        format = '%s %s' % (release.description, release.version) \
-                + ':%(dbname)s:%(levelname)s:%(name)s:%(message)s'
+        formatter = logging.Formatter("%s %s" % (release.description, release.version) + ':%(levelname)s:%(name)s:%(message)s')
 
     elif tools.config['logfile']:
         # LogFile Handler
@@ -213,17 +178,37 @@ def init_logger():
         # Normal Handler on standard output
         handler = logging.StreamHandler(sys.stdout)
 
-    if isinstance(handler, logging.StreamHandler) and os.isatty(handler.stream.fileno()):
-        formatter = ColoredFormatter(format)
-    else:
-        formatter = DBFormatter(format)
+
+    # tell the handler to use this format
     handler.setFormatter(formatter)
 
     # add the handler to the root logger
-    logger = logging.getLogger()
     logger.addHandler(handler)
     logger.setLevel(int(tools.config['log_level'] or '0'))
 
+    if (not isinstance(handler, logging.FileHandler)) and os.name != 'nt':
+        # change color of level names
+        # uses of ANSI color codes
+        # see http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html
+        # maybe use http://code.activestate.com/recipes/574451/
+        colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', None, 'default']
+        foreground = lambda f: 30 + colors.index(f)
+        background = lambda f: 40 + colors.index(f)
+
+        mapping = {
+            'DEBUG_RPC': ('blue', 'white'),
+            'DEBUG': ('blue', 'default'),
+            'INFO': ('green', 'default'),
+            'TEST': ('white', 'blue'),
+            'WARNING': ('yellow', 'default'),
+            'ERROR': ('red', 'default'),
+            'CRITICAL': ('white', 'red'),
+        }
+
+        for level, (fg, bg) in mapping.items():
+            msg = "\x1b[%dm\x1b[%dm%s\x1b[0m" % (foreground(fg), background(bg), level)
+            logging.addLevelName(getattr(logging, level), msg)
+
 
 class Logger(object):
     def __init__(self):
@@ -272,11 +257,8 @@ class Logger(object):
             # 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()
+    def set_loglevel(self, level):
+        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)
@@ -329,39 +311,17 @@ class Server:
     """
     __is_started = False
     __servers = []
-    __starter_threads = []
-
-    # we don't want blocking server calls (think select()) to
-    # wait forever and possibly prevent exiting the process,
-    # but instead we want a form of polling/busy_wait pattern, where
-    # _server_timeout should be used as the default timeout for
-    # all I/O blocking operations
-    _busywait_timeout = 0.5
 
 
     __logger = logging.getLogger('server')
 
     def __init__(self):
-        Server.__servers.append(self)
         if Server.__is_started:
-            # raise Exception('All instances of servers must be inited before the startAll()')
-            # Since the startAll() won't be called again, allow this server to
-            # init and then start it after 1sec (hopefully). Register that
-            # timer thread in a list, so that we can abort the start if quitAll
-            # is called in the meantime
-            t = threading.Timer(1.0, self._late_start)
-            t.name = 'Late start timer for %s' % str(self.__class__)
-            Server.__starter_threads.append(t)
-            t.start()
+            raise Exception('All instances of servers must be inited before the startAll()')
+        Server.__servers.append(self)
 
     def start(self):
         self.__logger.debug("called stub Server.start")
-        
-    def _late_start(self):
-        self.start()
-        for thr in Server.__starter_threads:
-            if thr.finished.is_set():
-                Server.__starter_threads.remove(thr)
 
     def stop(self):
         self.__logger.debug("called stub Server.stop")
@@ -384,11 +344,6 @@ class Server:
         if not cls.__is_started:
             return
         cls.__logger.info("Stopping %d services" % len(cls.__servers))
-        for thr in cls.__starter_threads:
-            if not thr.finished.is_set():
-                thr.cancel()
-            cls.__starter_threads.remove(thr)
-
         for srv in cls.__servers:
             srv.stop()
         cls.__is_started = False
@@ -399,21 +354,6 @@ class Server:
         res.extend(srv.stats() for srv in cls.__servers)
         return '\n'.join(res)
 
-    def _close_socket(self):
-        if os.name != 'nt':
-            try:
-                self.socket.shutdown(getattr(socket, 'SHUT_RDWR', 2))
-            except socket.error, e:
-                if e.errno != errno.ENOTCONN: raise
-                # OSX, socket shutdowns both sides if any side closes it
-                # causing an error 57 'Socket is not connected' on shutdown
-                # of the other side (or something), see
-                # http://bugs.python.org/issue4397
-                self.__logger.debug(
-                    '"%s" when shutting down server socket, '
-                    'this is normal under OS X', e)
-        self.socket.close()
-
 class OpenERPDispatcherException(Exception):
     def __init__(self, exception, traceback):
         self.exception = exception
@@ -421,10 +361,7 @@ class OpenERPDispatcherException(Exception):
 
 class OpenERPDispatcher:
     def log(self, title, msg):
-        logger = logging.getLogger(title)
-        if logger.isEnabledFor(logging.DEBUG_RPC):
-            for line in pformat(msg).split('\n'):
-                logger.log(logging.DEBUG_RPC, line)
+        Logger().notifyChannel('%s' % title, LOG_DEBUG_RPC, pformat(msg))
 
     def dispatch(self, service_name, method, params):
         try: