[imp] migrated to latest version of client
bzr revid: nicolas.vanhoren@openerp.com-20120105165633-med9y3078abchs5q
This commit is contained in:
parent
9b998a6551
commit
0baab517f1
|
@ -408,7 +408,7 @@ class Root(object):
|
|||
self.config = options
|
||||
|
||||
if self.config.backend == 'local':
|
||||
conn = openerplib.get_connector(protocol='local')
|
||||
conn = LocalConnector()
|
||||
else:
|
||||
conn = openerplib.get_connector(hostname=self.config.server_host,
|
||||
port=self.config.server_port)
|
||||
|
@ -522,4 +522,58 @@ class Root(object):
|
|||
return m
|
||||
return None
|
||||
|
||||
#
|
||||
class LibException(Exception):
|
||||
""" Base of all client lib exceptions """
|
||||
def __init__(self,code=None,message=None):
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
class ApplicationError(LibException):
|
||||
""" maps to code: 1, server side: Exception or openerp.exceptions.DeferredException"""
|
||||
|
||||
class Warning(LibException):
|
||||
""" maps to code: 2, server side: openerp.exceptions.Warning"""
|
||||
|
||||
class AccessError(LibException):
|
||||
""" maps to code: 3, server side: openerp.exceptions.AccessError"""
|
||||
|
||||
class AccessDenied(LibException):
|
||||
""" maps to code: 4, server side: openerp.exceptions.AccessDenied"""
|
||||
|
||||
|
||||
class LocalConnector(openerplib.Connector):
|
||||
"""
|
||||
A type of connector that uses the XMLRPC protocol.
|
||||
"""
|
||||
PROTOCOL = 'local'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
import openerp
|
||||
import traceback
|
||||
import xmlrpclib
|
||||
try:
|
||||
result = openerp.netsvc.dispatch_rpc(service_name, method, args)
|
||||
except Exception,e:
|
||||
# TODO change the except to raise LibException instead of their emulated xmlrpc fault
|
||||
if isinstance(e, openerp.osv.osv.except_osv):
|
||||
fault = xmlrpclib.Fault('warning -- ' + e.name + '\n\n' + e.value, '')
|
||||
elif isinstance(e, openerp.exceptions.Warning):
|
||||
fault = xmlrpclib.Fault('warning -- Warning\n\n' + str(e), '')
|
||||
elif isinstance(e, openerp.exceptions.AccessError):
|
||||
fault = xmlrpclib.Fault('warning -- AccessError\n\n' + str(e), '')
|
||||
elif isinstance(e, openerp.exceptions.AccessDenied):
|
||||
fault = xmlrpclib.Fault('AccessDenied', str(e))
|
||||
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)
|
||||
else:
|
||||
info = sys.exc_info()
|
||||
formatted_info = "".join(traceback.format_exception(*info))
|
||||
fault = xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
|
||||
raise fault
|
||||
return result
|
||||
|
||||
|
|
|
@ -36,52 +36,13 @@ Code repository: https://code.launchpad.net/~niv-openerp/openerp-client-lib/trun
|
|||
"""
|
||||
|
||||
import xmlrpclib
|
||||
import logging
|
||||
import socket
|
||||
import sys
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
except ImportError:
|
||||
import StringIO
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
def _getChildLogger(logger, subname):
|
||||
return logging.getLogger(logger.name + "." + subname)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Exceptions
|
||||
# TODO openerplib should raise those instead of xmlrpc faults:
|
||||
#----------------------------------------------------------
|
||||
|
||||
class LibException(Exception):
|
||||
""" Base of all client lib exceptions """
|
||||
def __init__(self,code=None,message=None):
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
class ApplicationError(LibException):
|
||||
""" maps to code: 1, server side: Exception or openerp.exceptions.DeferredException"""
|
||||
|
||||
class Warning(LibException):
|
||||
""" maps to code: 2, server side: openerp.exceptions.Warning"""
|
||||
|
||||
class AccessError(LibException):
|
||||
""" maps to code: 3, server side: openerp.exceptions.AccessError"""
|
||||
|
||||
class AccessDenied(LibException):
|
||||
""" maps to code: 4, server side: openerp.exceptions.AccessDenied"""
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Connectors
|
||||
#----------------------------------------------------------
|
||||
|
||||
class Connector(object):
|
||||
"""
|
||||
The base abstract class representing a connection to an OpenERP Server.
|
||||
|
@ -126,7 +87,6 @@ class XmlRPCConnector(Connector):
|
|||
def send(self, service_name, method, *args):
|
||||
url = '%s/%s' % (self.url, service_name)
|
||||
service = xmlrpclib.ServerProxy(url)
|
||||
# TODO should try except and wrap exception into LibException
|
||||
return getattr(service, method)(*args)
|
||||
|
||||
class XmlRPCSConnector(XmlRPCConnector):
|
||||
|
@ -141,145 +101,6 @@ class XmlRPCSConnector(XmlRPCConnector):
|
|||
super(XmlRPCSConnector, self).__init__(hostname, port)
|
||||
self.url = 'https://%s:%d/xmlrpc' % (self.hostname, self.port)
|
||||
|
||||
class NetRPC_Exception(Exception):
|
||||
"""
|
||||
Exception for NetRPC errors.
|
||||
"""
|
||||
def __init__(self, faultCode, faultString):
|
||||
self.faultCode = faultCode
|
||||
self.faultString = faultString
|
||||
self.args = (faultCode, faultString)
|
||||
|
||||
class NetRPC(object):
|
||||
"""
|
||||
Low level class for NetRPC protocol.
|
||||
"""
|
||||
def __init__(self, sock=None):
|
||||
if sock is None:
|
||||
self.sock = socket.socket(
|
||||
socket.AF_INET, socket.SOCK_STREAM)
|
||||
else:
|
||||
self.sock = sock
|
||||
self.sock.settimeout(120)
|
||||
def connect(self, host, port=False):
|
||||
if not port:
|
||||
buf = host.split('//')[1]
|
||||
host, port = buf.split(':')
|
||||
self.sock.connect((host, int(port)))
|
||||
|
||||
def disconnect(self):
|
||||
self.sock.shutdown(socket.SHUT_RDWR)
|
||||
self.sock.close()
|
||||
|
||||
def mysend(self, msg, exception=False, traceback=None):
|
||||
msg = pickle.dumps([msg,traceback])
|
||||
size = len(msg)
|
||||
self.sock.send('%8d' % size)
|
||||
self.sock.send(exception and "1" or "0")
|
||||
totalsent = 0
|
||||
while totalsent < size:
|
||||
sent = self.sock.send(msg[totalsent:])
|
||||
if sent == 0:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
totalsent = totalsent + sent
|
||||
|
||||
def myreceive(self):
|
||||
buf=''
|
||||
while len(buf) < 8:
|
||||
chunk = self.sock.recv(8 - len(buf))
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
buf += chunk
|
||||
size = int(buf)
|
||||
buf = self.sock.recv(1)
|
||||
if buf != "0":
|
||||
exception = buf
|
||||
else:
|
||||
exception = False
|
||||
msg = ''
|
||||
while len(msg) < size:
|
||||
chunk = self.sock.recv(size-len(msg))
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
msg = msg + chunk
|
||||
msgio = StringIO.StringIO(msg)
|
||||
unpickler = pickle.Unpickler(msgio)
|
||||
unpickler.find_global = None
|
||||
res = unpickler.load()
|
||||
|
||||
if isinstance(res[0],Exception):
|
||||
if exception:
|
||||
raise NetRPC_Exception(str(res[0]), str(res[1]))
|
||||
raise res[0]
|
||||
else:
|
||||
return res[0]
|
||||
|
||||
class NetRPCConnector(Connector):
|
||||
"""
|
||||
A type of connector that uses the NetRPC protocol.
|
||||
"""
|
||||
|
||||
PROTOCOL = 'netrpc'
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector.netrpc')
|
||||
|
||||
def __init__(self, hostname, port=8070):
|
||||
"""
|
||||
Initialize by specifying the hostname and the port.
|
||||
:param hostname: The hostname of the computer holding the instance of OpenERP.
|
||||
:param port: The port used by the OpenERP instance for NetRPC (default to 8070).
|
||||
"""
|
||||
Connector.__init__(self, hostname, port)
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
socket = NetRPC()
|
||||
socket.connect(self.hostname, self.port)
|
||||
socket.mysend((service_name, method, )+args)
|
||||
result = socket.myreceive()
|
||||
socket.disconnect()
|
||||
return result
|
||||
|
||||
class LocalConnector(Connector):
|
||||
"""
|
||||
A type of connector that uses the XMLRPC protocol.
|
||||
"""
|
||||
PROTOCOL = 'local'
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector.local')
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
import openerp
|
||||
import traceback
|
||||
try:
|
||||
result = openerp.netsvc.dispatch_rpc(service_name, method, args)
|
||||
except Exception,e:
|
||||
# TODO change the except to raise LibException instead of their emulated xmlrpc fault
|
||||
if isinstance(e, openerp.osv.osv.except_osv):
|
||||
fault = xmlrpclib.Fault('warning -- ' + e.name + '\n\n' + e.value, '')
|
||||
elif isinstance(e, openerp.exceptions.Warning):
|
||||
fault = xmlrpclib.Fault('warning -- Warning\n\n' + str(e), '')
|
||||
elif isinstance(e, openerp.exceptions.AccessError):
|
||||
fault = xmlrpclib.Fault('warning -- AccessError\n\n' + str(e), '')
|
||||
elif isinstance(e, openerp.exceptions.AccessDenied):
|
||||
fault = xmlrpclib.Fault('AccessDenied', str(e))
|
||||
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)
|
||||
else:
|
||||
info = sys.exc_info()
|
||||
formatted_info = "".join(traceback.format_exception(*info))
|
||||
fault = xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
|
||||
raise fault
|
||||
return result
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Public api
|
||||
#----------------------------------------------------------
|
||||
|
||||
class Service(object):
|
||||
"""
|
||||
A class to execute RPC calls on a specific service of the remote server.
|
||||
|
@ -319,7 +140,8 @@ class Connection(object):
|
|||
database=None,
|
||||
login=None,
|
||||
password=None,
|
||||
user_id=None):
|
||||
user_id=None,
|
||||
auto_context=True):
|
||||
"""
|
||||
Initialize with login information. The login information is facultative to allow specifying
|
||||
it after the initialization of this object.
|
||||
|
@ -330,10 +152,15 @@ class Connection(object):
|
|||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
:param auto_context: If true, automatically queries the context of the user and adds it to all
|
||||
method calls on models. If a context is already specified, the contexts are merged with it (the
|
||||
user context has the lowest priority). Default to True.
|
||||
"""
|
||||
self.connector = connector
|
||||
|
||||
self.set_login_info(database, login, password, user_id)
|
||||
self.user_context = None
|
||||
self.auto_context = auto_context
|
||||
|
||||
def set_login_info(self, database, login, password, user_id=None):
|
||||
"""
|
||||
|
@ -369,6 +196,16 @@ class Connection(object):
|
|||
if not self.user_id:
|
||||
raise AuthenticationError("Authentication failure")
|
||||
self.__logger.debug("Authenticated with user id %s", self.user_id)
|
||||
|
||||
def get_user_context(self):
|
||||
"""
|
||||
Query the default context of the user.
|
||||
"""
|
||||
if not self.user_context:
|
||||
mod = self.get_model('res.users')
|
||||
mod.override_auto_context = False
|
||||
self.user_context = mod.context_get()
|
||||
return self.user_context
|
||||
|
||||
def get_model(self, model_name):
|
||||
"""
|
||||
|
@ -407,6 +244,7 @@ class Model(object):
|
|||
"""
|
||||
self.connection = connection
|
||||
self.model_name = model_name
|
||||
self.override_auto_context = None
|
||||
self.__logger = _getChildLogger(_getChildLogger(_logger, 'object'), model_name or "")
|
||||
|
||||
def __getattr__(self, method):
|
||||
|
@ -415,19 +253,23 @@ class Model(object):
|
|||
|
||||
:param method: The method for the linked model (search, read, write, unlink, create, ...)
|
||||
"""
|
||||
def proxy(*args):
|
||||
def proxy(*args, **kw):
|
||||
"""
|
||||
:param args: A list of values for the method
|
||||
"""
|
||||
self.connection.check_login(False)
|
||||
self.__logger.debug(args)
|
||||
result = self.connection.get_service('object').execute(
|
||||
if (self.override_auto_context is not None and self.override_auto_context) or \
|
||||
(self.override_auto_context is None and self.connection.auto_context):
|
||||
kw = dict(kw)
|
||||
kw['context'] = dict(self.connection.get_user_context(), **kw.get('context', {}))
|
||||
result = self.connection.get_service('object').execute_kw(
|
||||
self.connection.database,
|
||||
self.connection.user_id,
|
||||
self.connection.password,
|
||||
self.model_name,
|
||||
method,
|
||||
*args)
|
||||
args, kw)
|
||||
if method == "read":
|
||||
if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
|
||||
index = {}
|
||||
|
@ -457,24 +299,20 @@ class Model(object):
|
|||
|
||||
def get_connector(hostname=None, protocol="xmlrpc", port="auto"):
|
||||
"""
|
||||
A shortcut method to easily create a connector to a remote server using XMLRPC or NetRPC.
|
||||
A shortcut method to easily create a connector to a remote server using XMLRPC.
|
||||
|
||||
:param hostname: The hostname to the remote server.
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "netrpc".
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "xmlrpcs".
|
||||
:param port: The number of the port. Defaults to auto.
|
||||
"""
|
||||
if port == 'auto':
|
||||
port = 8069 if protocol=="xmlrpc" else (8070 if protocol == "netrpc" else 8071)
|
||||
port = 8069 if protocol=="xmlrpc" else 8071
|
||||
if protocol == "xmlrpc":
|
||||
return XmlRPCConnector(hostname, port)
|
||||
elif protocol == "xmlrpcs":
|
||||
return XmlRPCSConnector(hostname, port)
|
||||
elif protocol == "netrpc":
|
||||
return NetRPCConnector(hostname, port)
|
||||
elif protocol == "local":
|
||||
return LocalConnector()
|
||||
else:
|
||||
raise ValueError("You must choose xmlrpc(s), netrpc or local")
|
||||
raise ValueError("You must choose xmlrpc or xmlrpcs")
|
||||
|
||||
def get_connection(hostname=None, protocol="xmlrpc", port='auto', database=None,
|
||||
login=None, password=None, user_id=None):
|
||||
|
@ -482,7 +320,7 @@ def get_connection(hostname=None, protocol="xmlrpc", port='auto', database=None,
|
|||
A shortcut method to easily create a connection to a remote OpenERP server.
|
||||
|
||||
:param hostname: The hostname to the remote server.
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "netrpc".
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "xmlrpcs".
|
||||
:param port: The number of the port. Defaults to auto.
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
|
|
|
@ -53,7 +53,7 @@ class OpenERPSession(object):
|
|||
|
||||
def build_connection(self):
|
||||
conn = openerplib.Connection(self.config.connector, database=self._db, login=self._login,
|
||||
user_id=self._uid, password=self._password)
|
||||
user_id=self._uid, password=self._password, auto_context=False)
|
||||
return conn
|
||||
|
||||
def proxy(self, service):
|
||||
|
|
Loading…
Reference in New Issue