[IMP] account_voucher: added case2_usd_eur_debtor_in_eur.yml
[odoo/odoo.git] / openerp / wsgi.py
index b7a948f..5a8f19f 100644 (file)
@@ -36,183 +36,64 @@ import signal
 import sys
 import threading
 import time
-import traceback
 
 import openerp
-import openerp.modules
 import openerp.tools.config as config
 import service.websrv_lib as websrv_lib
 
-# XML-RPC fault codes. Some care must be taken when changing these: the
-# constants are also defined client-side and must remain in sync.
-# User code must use the exceptions defined in ``openerp.exceptions`` (not
-# create directly ``xmlrpclib.Fault`` objects).
-XML_RPC_FAULT_CODE_CLIENT_ERROR = 1 # again, indistinguishable from app. error.
-XML_RPC_FAULT_CODE_APPLICATION_ERROR = 1
-# Unused, deferred errors are indistinguishable from normal application
-# errors. We keep them so we can use the word 'indistinguishable' twice
-# in the same comment.
-XML_RPC_FAULT_CODE_DEFERRED_APPLICATION_ERROR = 2
-XML_RPC_FAULT_CODE_ACCESS_DENIED = 3
-XML_RPC_FAULT_CODE_ACCESS_ERROR = 4
-XML_RPC_FAULT_CODE_WARNING = 5
-
-# The new (6.1) versioned RPC paths.
-XML_RPC_PATH = '/openerp/xmlrpc'
-XML_RPC_PATH_1 = '/openerp/xmlrpc/1'
-JSON_RPC_PATH = '/openerp/jsonrpc'
-JSON_RPC_PATH_1 = '/openerp/jsonrpc/1'
-
-def xmlrpc_return(start_response, service, method, params, legacy_exceptions=False):
-    """
-    Helper to call a service's method with some params, using a wsgi-supplied
-    ``start_response`` callback.
-
-    This is the place to look at to see the mapping between core exceptions
-    and XML-RPC fault codes.
-    """
-    # Map OpenERP core exceptions to XML-RPC fault codes. Specific exceptions
-    # defined in ``openerp.exceptions`` are mapped to specific fault codes;
-    # all the other exceptions are mapped to the generic
-    # XML_RPC_FAULT_CODE_APPLICATION_ERROR value.
-    # This also mimics SimpleXMLRPCDispatcher._marshaled_dispatch() for
-    # exception handling.
+def xmlrpc_return(start_response, service, method, params):
+    """ Helper to call a service's method with some params, using a
+    wsgi-supplied ``start_response`` callback."""
+    # This mimics SimpleXMLRPCDispatcher._marshaled_dispatch() for exception
+    # handling.
     try:
-        result = openerp.netsvc.dispatch_rpc(service, method, params)
+        result = openerp.netsvc.dispatch_rpc(service, method, params, None) # TODO auth
         response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False, encoding=None)
-    except Exception, e:
-        if legacy_exceptions:
-            response = xmlrpc_handle_exception_legacy(e)
-        else:
-            response = xmlrpc_handle_exception(e)
-    start_response("200 OK", [('Content-Type','text/xml'), ('Content-Length', str(len(response)))])
-    return [response]
-
-def xmlrpc_handle_exception(e):
-    if isinstance(e, openerp.osv.osv.except_osv): # legacy
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_WARNING, openerp.tools.ustr(e.value))
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.Warning):
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_WARNING, str(e))
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance (e, openerp.exceptions.AccessError):
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_ACCESS_ERROR, str(e))
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.AccessDenied):
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_ACCESS_DENIED, str(e))
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.DeferredException):
-        info = e.traceback
-        # Which one is the best ?
-        formatted_info = "".join(traceback.format_exception(*info))
-        #formatted_info = openerp.tools.exception_to_unicode(e) + '\n' + info
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_APPLICATION_ERROR, formatted_info)
+    except openerp.netsvc.OpenERPDispatcherException, e:
+        fault = xmlrpclib.Fault(openerp.tools.exception_to_unicode(e.exception), e.traceback)
         response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    else:
-        if hasattr(e, 'message') and e.message == 'AccessDenied': # legacy
-            fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_ACCESS_DENIED, str(e))
-            response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-        else:
-            info = sys.exc_info()
-            # Which one is the best ?
-            formatted_info = "".join(traceback.format_exception(*info))
-            #formatted_info = openerp.tools.exception_to_unicode(e) + '\n' + info
-            fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_APPLICATION_ERROR, formatted_info)
-            response = xmlrpclib.dumps(fault, allow_none=None, encoding=None)
-    return response
-
-def xmlrpc_handle_exception_legacy(e):
-    if isinstance(e, openerp.osv.osv.except_osv):
-        fault = xmlrpclib.Fault('warning -- ' + e.name + '\n\n' + e.value, '')
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.Warning):
-        fault = xmlrpclib.Fault('warning -- Warning\n\n' + str(e), '')
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.AccessError):
-        fault = xmlrpclib.Fault('warning -- AccessError\n\n' + str(e), '')
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.AccessDenied):
-        fault = xmlrpclib.Fault('AccessDenied', str(e))
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    elif isinstance(e, openerp.exceptions.DeferredException):
-        info = e.traceback
-        formatted_info = "".join(traceback.format_exception(*info))
-        fault = xmlrpclib.Fault(openerp.tools.ustr(e.message), formatted_info)
-        response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-    else:
-        info = sys.exc_info()
-        formatted_info = "".join(traceback.format_exception(*info))
-        fault = xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
+    except:
+        exc_type, exc_value, exc_tb = sys.exc_info()
+        fault = xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value))
         response = xmlrpclib.dumps(fault, allow_none=None, encoding=None)
-    return response
+    start_response("200 OK", [('Content-Type','text/xml'), ('Content-Length', str(len(response)))])
+    return [response]
 
-def wsgi_xmlrpc_1(environ, start_response):
+def wsgi_xmlrpc(environ, start_response):
     """ The main OpenERP WSGI handler."""
-    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith(XML_RPC_PATH_1):
+    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/openerp/xmlrpc'):
         length = int(environ['CONTENT_LENGTH'])
         data = environ['wsgi.input'].read(length)
 
         params, method = xmlrpclib.loads(data)
 
-        path = environ['PATH_INFO'][len(XML_RPC_PATH_1):]
+        path = environ['PATH_INFO'][len('/openerp/xmlrpc'):]
         if path.startswith('/'): path = path[1:]
         if path.endswith('/'): p = path[:-1]
         path = path.split('/')
 
-        # All routes are hard-coded.
+        # All routes are hard-coded. Need a way to register addons-supplied handlers.
 
         # No need for a db segment.
         if len(path) == 1:
             service = path[0]
 
             if service == 'common':
-                if method in ('server_version',):
-                    service = 'db'
-            return xmlrpc_return(start_response, service, method, params)
-
+                if method in ('create_database', 'list', 'server_version'):
+                    return xmlrpc_return(start_response, 'db', method, params)
+                else:
+                    return xmlrpc_return(start_response, 'common', method, params)
         # A db segment must be given.
         elif len(path) == 2:
             service, db_name = path
             params = (db_name,) + params
 
-            return xmlrpc_return(start_response, service, method, params)
-
-        # A db segment and a model segment must be given.
-        elif len(path) == 3 and path[0] == 'model':
-            service, db_name, model_name = path
-            params = (db_name,) + params[:2] + (model_name,) + params[2:]
-            service = 'object'
-            return xmlrpc_return(start_response, service, method, params)
+            if service == 'model':
+                return xmlrpc_return(start_response, 'object', method, params)
+            elif service == 'report':
+                return xmlrpc_return(start_response, 'report', method, params)
 
-        # The body has been read, need to raise an exception (not return None).
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_CLIENT_ERROR, '')
-        response = xmlrpclib.dumps(fault, allow_none=None, encoding=None)
-        start_response("200 OK", [('Content-Type','text/xml'), ('Content-Length', str(len(response)))])
-        return [response]
-
-def wsgi_xmlrpc(environ, start_response):
-    """ WSGI handler to return the versions."""
-    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith(XML_RPC_PATH):
-        length = int(environ['CONTENT_LENGTH'])
-        data = environ['wsgi.input'].read(length)
-
-        params, method = xmlrpclib.loads(data)
-
-        path = environ['PATH_INFO'][len(XML_RPC_PATH):]
-        if path.startswith('/'): path = path[1:]
-        if path.endswith('/'): p = path[:-1]
-        path = path.split('/')
-
-        # All routes are hard-coded.
-
-        if len(path) == 1 and path[0] == '' and method in ('version',):
-            return xmlrpc_return(start_response, 'common', method, ())
-
-        # The body has been read, need to raise an exception (not return None).
-        fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_CLIENT_ERROR, '')
-        response = xmlrpclib.dumps(fault, allow_none=None, encoding=None)
-        start_response("200 OK", [('Content-Type','text/xml'), ('Content-Length', str(len(response)))])
-        return [response]
+        # TODO the body has been read, need to raise an exception (not return None).
 
 def legacy_wsgi_xmlrpc(environ, start_response):
     if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/xmlrpc/'):
@@ -221,7 +102,7 @@ def legacy_wsgi_xmlrpc(environ, start_response):
         path = environ['PATH_INFO'][len('/xmlrpc/'):] # expected to be one of db, object, ...
 
         params, method = xmlrpclib.loads(data)
-        return xmlrpc_return(start_response, path, method, params, True)
+        return xmlrpc_return(start_response, path, method, params)
 
 def wsgi_jsonrpc(environ, start_response):
     pass
@@ -391,7 +272,6 @@ def application(environ, start_response):
 
     # Try all handlers until one returns some result (i.e. not None).
     wsgi_handlers = [
-        wsgi_xmlrpc_1,
         wsgi_xmlrpc,
         wsgi_jsonrpc,
         legacy_wsgi_xmlrpc,