Files
tryton/tryton/rpc.py
T

215 lines
5.9 KiB
Python

#This file is part of Tryton. The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms.
import pysocket
import logging
import socket
from threading import Semaphore
_SOCK = None
_USER = 0
_USERNAME = ''
_SESSION = ''
_DATABASE = ''
CONTEXT = {}
_VIEW_CACHE = {}
TIMEZONE = 'utc'
SECURE = False
_SEMAPHORE = Semaphore()
def db_list(host, port):
global _SOCK, SECURE
_SEMAPHORE.acquire()
try:
try:
if _SOCK and (_SOCK.hostname != host or _SOCK.port != port):
_SOCK.disconnect()
if _SOCK is None:
_SOCK = pysocket.PySocket()
if not _SOCK.connected:
_SOCK.connect(host, port)
try:
_SOCK.send(('db', 'list'))
except Exception, exception:
if exception[0] == 32:
_SOCK.reconnect()
_SOCK.send(('db', 'list'))
else:
raise
res = _SOCK.receive()
SECURE = _SOCK.ssl
finally:
_SEMAPHORE.release()
return res
except:
return None
def db_exec(host, port, method, *args):
global _SOCK, SECURE
_SEMAPHORE.acquire()
try:
try:
if _SOCK and (_SOCK.hostname != host or _SOCK.port != port):
_SOCK.disconnect()
if _SOCK is None:
_SOCK= pysocket.PySocket()
if not _SOCK.connected:
_SOCK.connect(host, port)
_SOCK.send(('db', method) + args)
res = _SOCK.receive()
SECURE = _SOCK.ssl
finally:
_SEMAPHORE.release()
return res
except:
raise
def server_version(host, port):
global _SOCK, SECURE
_SEMAPHORE.acquire()
try:
try:
if _SOCK and (_SOCK.hostname != host or _SOCK.port != port):
_SOCK.disconnect()
if _SOCK is None:
_SOCK = pysocket.PySocket()
if not _SOCK.connected:
_SOCK.connect(host, port)
try:
_SOCK.send(('common', 'version'))
except Exception, exception:
if exception[0] == 32:
_SOCK.reconnect()
_SOCK.send(('db', 'list'))
else:
raise
res = _SOCK.receive()
SECURE = _SOCK.ssl
finally:
_SEMAPHORE.release()
return res
except:
return None
def login(username, password, host, port, database):
global _SOCK, _USER, _USERNAME, _SESSION, _DATABASE, _VIEW_CACHE, SECURE
_VIEW_CACHE = {}
SECURE = False
try:
_SEMAPHORE.acquire()
try:
if _SOCK and (_SOCK.hostname != host or _SOCK.port != port):
_SOCK.disconnect()
if _SOCK is None:
_SOCK = pysocket.PySocket()
if not _SOCK.connected:
_SOCK.connect(host, port)
_SOCK.send(('common', 'login', database, username, password))
res = _SOCK.receive()
finally:
_SEMAPHORE.release()
except socket.error:
_SOCK.reconnect()
_USER = 0
_SESSION = ''
return -1
if not res:
_USER = 0
_SESSION = ''
return -2
_USER = res[0]
_USERNAME = username
_SESSION = res[1]
_DATABASE = database
SECURE = _SOCK.ssl
context_reload()
return 1
def logout():
global _SOCK, _USER, _USERNAME, _SESSION, _DATABASE, _VIEW_CACHE, SECURE
if _SOCK:
_SOCK.disconnect()
_SOCK = None
_USER = 0
_USERNAME = ''
_SESSION = ''
_DATABASE = ''
_VIEW_CACHE = {}
SECURE = False
def context_reload():
global CONTEXT, TIMEZONE
user = RPCProxy('res.user')
try:
context = user.get_preferences(True, {})
except:
return
CONTEXT = {}
for i in context:
value = context[i]
CONTEXT[i] = value
if i == 'timezone':
try:
TIMEZONE = execute('common', 'timezone_get')
except:
pass
def _execute(blocking, obj, method, *args):
global _SOCK, _DATABASE, _USER, _SESSION
if not _SOCK or not _SOCK.connected:
raise Exception('NotLogged')
logging.getLogger('rpc.request').info(str((obj, method, args)))
key = False
if len(args) >= 6 and args[1] == 'fields_view_get':
key = str(args)
if key in _VIEW_CACHE and _VIEW_CACHE[key][0]:
args = args[:]
args = args + (_VIEW_CACHE[key][0],)
res = _SEMAPHORE.acquire(blocking)
if not res:
return
try:
try:
_SOCK.send((obj, method, _DATABASE, _USER, _SESSION) + args)
result = _SOCK.receive()
except socket.error:
try:
_SOCK.reconnect()
_SOCK.send((obj, method, _DATABASE, _USER, _SESSION) + args)
result = _SOCK.receive()
except socket.error:
_SOCK.reconnect()
raise
finally:
_SEMAPHORE.release()
if key:
if result is True and key in _VIEW_CACHE:
result = _VIEW_CACHE[key][1]
else:
_VIEW_CACHE[key] = (result['md5'], result)
return result
def execute(obj, method, *args):
return _execute(True, obj, method, *args)
def execute_nonblocking(obj, method, *args):
return _execute(False, obj, method, *args)
class RPCProxy(object):
def __init__(self, name):
self.name = name
self.__attrs = {}
def __getattr__(self, attr):
if attr not in self.__attrs:
self.__attrs[attr] = RPCFunction(self.name, attr)
return self.__attrs[attr]
class RPCFunction(object):
def __init__(self, name, func_name):
self.name = name
self.func = func_name
def __call__(self, *args):
return execute('object', 'execute', self.name, self.func, *args)