[FIX] purchase: cr -> self.cr in report
[odoo/odoo.git] / bin / netsvc.py
index e0e97ef..475bbc3 100644 (file)
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ##############################################################################
 #
 #
 ##############################################################################
 
-import SimpleXMLRPCServer
-import SocketServer
 import logging
 import logging.handlers
-import os
-import signal
-import socket
 import sys
 import threading
 import time
-import xmlrpclib
 import release
+from pprint import pformat
+import warnings
 
 class Service(object):
-    """ Base class for *Local* services 
-   
+    """ Base class for *Local* services
+
         Functionality here is trusted, no authentication.
     """
     _services = {}
@@ -51,8 +48,14 @@ class Service(object):
         raise Exception("No group for local services")
         #GROUPS.setdefault(name, {})[self.__name] = self
 
-    def service_exist(self,name):
-        return Service._services.has_key(name)
+    @classmethod
+    def exists(cls, name):
+        return name in cls._services
+
+    @classmethod
+    def remove(cls, name):
+        if cls.exists(name):
+            cls._services.pop(name)
 
     def exportMethod(self, method):
         if callable(method):
@@ -70,6 +73,7 @@ class LocalService(object):
         Any instance of this class will behave like the single instance
         of Service(name)
     """
+    __logger = logging.getLogger('service')
     def __init__(self, name):
         self.__name = name
         try:
@@ -77,8 +81,9 @@ class LocalService(object):
             for method_name, method_definition in self._service._methods.items():
                 setattr(self, method_name, method_definition)
         except KeyError, keyError:
-            Logger().notifyChannel('module', LOG_ERROR, 'This service does not exist: %s' % (str(keyError),) )
+            self.__logger.error('This service does not exist: %s' % (str(keyError),) )
             raise
+
     def __call__(self, method, *params):
         return getattr(self, method)(*params)
 
@@ -122,15 +127,17 @@ class ExportService(object):
 LOG_NOTSET = 'notset'
 LOG_DEBUG_RPC = 'debug_rpc'
 LOG_DEBUG = 'debug'
-LOG_DEBUG2 = 'debug2'
+LOG_TEST = 'test'
 LOG_INFO = 'info'
 LOG_WARNING = 'warn'
 LOG_ERROR = 'error'
 LOG_CRITICAL = 'critical'
 
-# add new log level below DEBUG
-logging.DEBUG2 = logging.DEBUG - 1
-logging.DEBUG_RPC = logging.DEBUG2 - 1
+logging.DEBUG_RPC = logging.DEBUG - 2
+logging.addLevelName(logging.DEBUG_RPC, 'DEBUG_RPC')
+
+logging.TEST = logging.INFO - 5
+logging.addLevelName(logging.TEST, 'TEST')
 
 def init_logger():
     import os
@@ -144,9 +151,7 @@ def init_logger():
     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')
         formatter = logging.Formatter("%s %s" % (release.description, release.version) + ':%(levelname)s:%(name)s:%(message)s')
@@ -190,9 +195,9 @@ def init_logger():
 
         mapping = {
             'DEBUG_RPC': ('blue', 'white'),
-            'DEBUG2': ('green', 'white'),
             'DEBUG': ('blue', 'default'),
             'INFO': ('green', 'default'),
+            'TEST': ('white', 'blue'),
             'WARNING': ('yellow', 'default'),
             'ERROR': ('red', 'default'),
             'CRITICAL': ('white', 'red'),
@@ -204,19 +209,24 @@ def init_logger():
 
 
 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 == LOG_DEBUG2 and not hasattr(log, level):
-            fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG2, msg, *args, **kwargs)
-            setattr(log, LOG_DEBUG2, fct)
+        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)
 
-        if level == LOG_DEBUG_RPC and not hasattr(log, level):
-            fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs)
-            setattr(log, LOG_DEBUG_RPC, fct)
 
         level_method = getattr(log, level)
 
@@ -225,7 +235,7 @@ class Logger(object):
 
         try:
             msg = tools.ustr(msg).strip()
-            if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',False):
+            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')
@@ -261,10 +271,12 @@ class Agent(object):
     _timers = {}
     _logger = Logger()
 
+    __logger = logging.getLogger('timer')
+
     def setAlarm(self, fn, dt, db_name, *args, **kwargs):
         wait = dt - time.time()
         if wait > 0:
-            self._logger.notifyChannel('timers', LOG_DEBUG, "Job scheduled in %.3g seconds for %s.%s" % (wait, fn.im_class.__name__, fn.func_name))
+            self.__logger.debug("Job scheduled in %.3g seconds for %s.%s" % (wait, fn.im_class.__name__, fn.func_name))
             timer = threading.Timer(wait, fn, args, kwargs)
             timer.start()
             self._timers.setdefault(db_name, []).append(timer)
@@ -291,25 +303,26 @@ import traceback
 class Server:
     """ Generic interface for all servers with an event loop etc.
         Override this to impement http, net-rpc etc. servers.
-        
+
         Servers here must have threaded behaviour. start() must not block,
         there is no run().
     """
     __is_started = False
     __servers = []
-    
+
+
+    __logger = logging.getLogger('server')
+
     def __init__(self):
         if Server.__is_started:
             raise Exception('All instances of servers must be inited before the startAll()')
         Server.__servers.append(self)
 
     def start(self):
-        print "called stub Server.start"
-        pass
-        
+        self.__logger.debug("called stub Server.start")
+
     def stop(self):
-        print "called stub Server.stop"
-        pass
+        self.__logger.debug("called stub Server.stop")
 
     def stats(self):
         """ This function should return statistics about the server """
@@ -319,35 +332,25 @@ class Server:
     def startAll(cls):
         if cls.__is_started:
             return
-        Logger().notifyChannel("services", LOG_INFO, 
-            "Starting %d services" % len(cls.__servers))
+        cls.__logger.info("Starting %d services" % len(cls.__servers))
         for srv in cls.__servers:
             srv.start()
         cls.__is_started = True
-    
+
     @classmethod
     def quitAll(cls):
         if not cls.__is_started:
             return
-        Logger().notifyChannel("services", LOG_INFO, 
-            "Stopping %d services" % len(cls.__servers))
+        cls.__logger.info("Stopping %d services" % len(cls.__servers))
         for srv in cls.__servers:
             srv.stop()
         cls.__is_started = False
 
     @classmethod
     def allStats(cls):
-        res = ''
-        if cls.__is_started:
-            res += "Servers started\n"
-        else:
-            res += "Servers stopped\n"
-        for srv in cls.__servers:
-            try:
-                res += srv.stats() + "\n"
-            except:
-                pass
-        return res
+        res = ["Servers %s" % ('stopped', 'started')[cls.__is_started]]
+        res.extend(srv.stats() for srv in cls.__servers)
+        return '\n'.join(res)
 
 class OpenERPDispatcherException(Exception):
     def __init__(self, exception, traceback):
@@ -356,7 +359,6 @@ class OpenERPDispatcherException(Exception):
 
 class OpenERPDispatcher:
     def log(self, title, msg):
-        from pprint import pformat
         Logger().notifyChannel('%s' % title, LOG_DEBUG_RPC, pformat(msg))
 
     def dispatch(self, service_name, method, params):