Use JSON-RPC
This commit is contained in:
1 parent
25a3c46af2
commit
d1daa78935
17 files changed
+386
-464
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Use JSON-RPC
|
||||
* Limit size of field when possible
|
||||
* Add xalign and yalign as fields attributes
|
||||
* Convert many popup to be no-modal
|
||||
|
||||
+11
-12
@@ -200,7 +200,7 @@ def request_server(server_widget):
|
||||
xoptions=gtk.FILL)
|
||||
entry_port = gtk.Entry()
|
||||
entry_port.set_max_length(5)
|
||||
entry_port.set_text("8070")
|
||||
entry_port.set_text("8000")
|
||||
entry_port.set_activates_default(True)
|
||||
entry_port.set_width_chars(16)
|
||||
table.attach(entry_port, 1, 2, 1, 2, yoptions=False,
|
||||
@@ -966,10 +966,9 @@ def to_xml(string):
|
||||
PLOCK = Lock()
|
||||
|
||||
def process_exception(exception, *args):
|
||||
global _USERNAME, _DATABASE, _SOCK
|
||||
|
||||
if isinstance(exception, TrytonError):
|
||||
if exception.ex_type == 'BadFingerprint':
|
||||
if exception.faultCode == 'BadFingerprint':
|
||||
warning(
|
||||
_('The server fingerprint has changed since last connection!\n'
|
||||
'The application will stop connecting to this server '
|
||||
@@ -977,13 +976,13 @@ def process_exception(exception, *args):
|
||||
from tryton.gui.main import Main
|
||||
Main.sig_quit()
|
||||
sys.exit()
|
||||
elif exception.ex_type == 'NotLogged':
|
||||
if not rpc._SOCK:
|
||||
elif exception.faultCode == 'NotLogged':
|
||||
if rpc.CONNECTION is None:
|
||||
message(_('Connection error!\n' \
|
||||
'Unable to connect to the server!'))
|
||||
return False
|
||||
elif isinstance(exception, TrytonServerError):
|
||||
if exception.ex_type == 'UserWarning':
|
||||
if exception.faultCode == 'UserWarning':
|
||||
msg = ''
|
||||
if len(exception.args) > 4:
|
||||
msg = exception.args[3]
|
||||
@@ -1005,13 +1004,13 @@ def process_exception(exception, *args):
|
||||
return process_exception(exception, *args)
|
||||
return True
|
||||
return False
|
||||
elif exception.ex_type == 'UserError':
|
||||
elif exception.faultCode == 'UserError':
|
||||
msg = ''
|
||||
if len(exception.args) > 3:
|
||||
msg = exception.args[2]
|
||||
warning(str(msg), str(exception.args[1]))
|
||||
return False
|
||||
elif exception.ex_type == 'ConcurrencyException':
|
||||
elif exception.faultCode == 'ConcurrencyException':
|
||||
if len(args) >= 6:
|
||||
if concurrency(args[1], args[3][0], args[5]):
|
||||
if '_timestamp' in args[5]:
|
||||
@@ -1024,11 +1023,11 @@ def process_exception(exception, *args):
|
||||
else:
|
||||
message(_('Concurrency Exception'), msg_type=gtk.MESSAGE_ERROR)
|
||||
return False
|
||||
elif exception.ex_type == 'NotLogged':
|
||||
elif exception.faultCode == 'NotLogged':
|
||||
if not PLOCK.acquire(False):
|
||||
return False
|
||||
hostname = rpc._SOCK.hostname
|
||||
port = rpc._SOCK.port
|
||||
hostname = rpc._HOST
|
||||
port = rpc._PORT
|
||||
try:
|
||||
while True:
|
||||
password = ask(_('Password:'), visibility=False)
|
||||
@@ -1060,7 +1059,7 @@ def process_exception(exception, *args):
|
||||
return False
|
||||
|
||||
if isinstance(exception, TrytonServerError):
|
||||
error_title, error_detail = exception.ex_type, exception.traceback
|
||||
error_title, error_detail = exception.faultCode, exception.faultString
|
||||
else:
|
||||
error_title = str(exception)
|
||||
error_detail = traceback.format_exc()
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class ConfigManager(object):
|
||||
'login.profile': demo_server,
|
||||
'login.login': 'demo',
|
||||
'login.server': demo_server,
|
||||
'login.port': '8070',
|
||||
'login.port': '8000',
|
||||
'login.db': demo_database,
|
||||
'login.expanded': False,
|
||||
'tip.autostart': False,
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from jsonrpc import Fault
|
||||
|
||||
|
||||
class TrytonServerError(Exception):
|
||||
|
||||
def __init__(self, *args):
|
||||
super(TrytonServerError, self).__init__(*args)
|
||||
self.ex_type = str(args[0])
|
||||
self.traceback = args[-1]
|
||||
TrytonServerError = Fault
|
||||
|
||||
|
||||
class TrytonError(Exception):
|
||||
|
||||
def __init__(self, ex_type):
|
||||
self.ex_type = ex_type
|
||||
def __init__(self, faultCode):
|
||||
self.faultCode = faultCode
|
||||
@@ -19,21 +19,19 @@ class Fingerprints(dict):
|
||||
for line in known_hosts:
|
||||
line = line.strip()
|
||||
try:
|
||||
key, sha1 = line.split(' ')
|
||||
host, port = key.rsplit(':', 1)
|
||||
host, sha1 = line.split(' ')
|
||||
except ValueError:
|
||||
continue
|
||||
self[(host, port)] = sha1
|
||||
self[host] = sha1
|
||||
|
||||
def save(self):
|
||||
lines = []
|
||||
with open(KNOWN_HOSTS_PATH, 'w') as known_hosts:
|
||||
known_hosts.writelines('%s:%s %s' % (host, port, sha1)
|
||||
+ os.linesep for (host, port), sha1 in self.iteritems())
|
||||
known_hosts.writelines('%s %s' % (host, sha1)
|
||||
+ os.linesep for host, sha1 in self.iteritems())
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
assert isinstance(key, tuple)
|
||||
assert len(key) == 2
|
||||
assert isinstance(key, basestring)
|
||||
assert len(value) == 59 # len of formated sha1
|
||||
super(Fingerprints, self).__setitem__(key, value)
|
||||
self.save()
|
||||
+6
-10
@@ -889,7 +889,7 @@ class Main(object):
|
||||
try:
|
||||
res = DBLogin().run()
|
||||
except TrytonError, exception:
|
||||
if exception.ex_type == 'QueryCanceled':
|
||||
if exception.faultCode == 'QueryCanceled':
|
||||
return False
|
||||
except TrytonServerError, exception:
|
||||
common.process_exception(exception)
|
||||
@@ -982,12 +982,8 @@ class Main(object):
|
||||
return True
|
||||
|
||||
def refresh_ssl(self):
|
||||
if rpc.SECURE:
|
||||
info = ''
|
||||
if hasattr(rpc._SOCK.ssl_sock, 'server'):
|
||||
info = str(rpc._SOCK.ssl_sock.server())
|
||||
self.tooltips.set_tip(self.secure_img, _('SSL connection') + \
|
||||
'\n' + info)
|
||||
if rpc.CONNECTION is not None and rpc.CONNECTION.ssl:
|
||||
self.tooltips.set_tip(self.secure_img, _('SSL connection'))
|
||||
self.secure_img.show()
|
||||
else:
|
||||
self.secure_img.hide()
|
||||
@@ -1044,7 +1040,7 @@ class Main(object):
|
||||
return False
|
||||
self.sb_username.set_text(prefs.get('status_bar', ''))
|
||||
self.sb_servername.set_text('%s@%s:%d/%s' % (rpc._USERNAME,
|
||||
rpc._SOCK.hostname, rpc._SOCK.port, rpc._DATABASE))
|
||||
rpc._HOST, rpc._PORT, rpc._DATABASE))
|
||||
if not prefs[menu_type]:
|
||||
if quiet:
|
||||
return False
|
||||
@@ -1396,8 +1392,8 @@ class Main(object):
|
||||
+ [CONFIG.defaults['login.port']])[:2]
|
||||
database, path = (urlp.path[1:].split('/', 1) + [None])[:2]
|
||||
if (not path or
|
||||
hostname != rpc._SOCK.hostname or
|
||||
int(port) != rpc._SOCK.port or
|
||||
hostname != rpc._HOST or
|
||||
int(port) != rpc._PORT or
|
||||
database != rpc._DATABASE):
|
||||
return
|
||||
type_, path = (path.split('/', 1) + [''])[:2]
|
||||
|
||||
@@ -29,7 +29,7 @@ class DBCreate(object):
|
||||
self.entry_server_connection.modify_text(gtk.STATE_INSENSITIVE, \
|
||||
gtk.gdk.color_parse(common.COLOR_SCHEMES["black"]))
|
||||
self.tooltips.set_tip(self.entry_server_connection,_("This is the URL of " \
|
||||
"the Tryton server. Use server 'localhost' and port '8070' if " \
|
||||
"the Tryton server. Use server 'localhost' and port '8000' if " \
|
||||
"the server is installed on this computer. Click on 'Change' to " \
|
||||
"change the address."))
|
||||
else:
|
||||
@@ -50,7 +50,7 @@ class DBCreate(object):
|
||||
"2. Find out on which address and port it is listen.\n" \
|
||||
"3. If there is a firewall between the server and this " \
|
||||
"client, make shure that the server address and port " \
|
||||
"(usually 8070) are not blocked.\n" \
|
||||
"(usually 8000) are not blocked.\n" \
|
||||
"Click on 'Change' to change the address."))
|
||||
return state
|
||||
|
||||
@@ -177,7 +177,7 @@ class DBCreate(object):
|
||||
self.entry_server_connection.unset_flags(gtk.CAN_FOCUS)
|
||||
self.entry_server_connection.set_editable(False)
|
||||
self.tooltips.set_tip(self.entry_server_connection, _("This is the URL of " \
|
||||
"the server. Use server 'localhost' and port '8070' if " \
|
||||
"the server. Use server 'localhost' and port '8000' if " \
|
||||
"the server is installed on this computer. Click on 'Change' to " \
|
||||
"change the address."))
|
||||
self.button_server_change = gtk.Button(_("C_hange"), stock=None,
|
||||
|
||||
@@ -136,7 +136,7 @@ class DBBackupDrop(object):
|
||||
self.entry_server_connection.unset_flags(gtk.CAN_FOCUS)
|
||||
self.entry_server_connection.set_editable(False)
|
||||
self.tooltips.set_tip(self.entry_server_connection, _("This is the " \
|
||||
"URL of the server. Use server 'localhost' and port '8070' " \
|
||||
"URL of the server. Use server 'localhost' and port '8000' " \
|
||||
"if the server is installed on this computer. " \
|
||||
"Click on 'Change' to change the address."))
|
||||
table.attach(self.entry_server_connection, 1, 2, 2, 3,
|
||||
|
||||
@@ -169,7 +169,7 @@ class DBListEditor(object):
|
||||
for entryname in ('host', 'port', 'database', 'username'):
|
||||
entry = getattr(self, '%s_entry' % entryname)
|
||||
if entryname == 'port':
|
||||
entry.set_text('8070')
|
||||
entry.set_text('8000')
|
||||
else:
|
||||
entry.set_text('')
|
||||
self.current_database = None
|
||||
@@ -464,13 +464,13 @@ class DBLogin(object):
|
||||
|
||||
# Profile informations
|
||||
self.profile_cfg = os.path.join(get_config_dir(), 'profiles.cfg')
|
||||
self.profiles = ConfigParser.SafeConfigParser({'port': '8070'})
|
||||
self.profiles = ConfigParser.SafeConfigParser({'port': '8000'})
|
||||
if not os.path.exists(self.profile_cfg):
|
||||
short_version = '.'.join(VERSION.split('.', 2)[:2])
|
||||
name = 'demo%s.tryton.org' % short_version
|
||||
self.profiles.add_section(name)
|
||||
self.profiles.set(name, 'host', name)
|
||||
self.profiles.set(name, 'port', '8070')
|
||||
self.profiles.set(name, 'port', '8000')
|
||||
self.profiles.set(name, 'database', 'demo%s' % short_version)
|
||||
self.profiles.set(name, 'username', 'demo')
|
||||
else:
|
||||
@@ -565,7 +565,7 @@ class DBLogin(object):
|
||||
if ':' in netloc:
|
||||
return int(netloc.split(':')[1])
|
||||
else:
|
||||
return 8070
|
||||
return 8000
|
||||
|
||||
def run(self):
|
||||
profile_name = CONFIG['login.profile']
|
||||
|
||||
@@ -83,7 +83,7 @@ class DBRestore(object):
|
||||
self.entry_server_url.set_activates_default(True)
|
||||
self.entry_server_url.set_width_chars(16)
|
||||
self.tooltips.set_tip(self.entry_server_url, _("This is the URL of " \
|
||||
"the server. Use server 'localhost' and port '8070' if " \
|
||||
"the server. Use server 'localhost' and port '8000' if " \
|
||||
"the server is installed on this computer. Click on " \
|
||||
"'Change' to change the address."))
|
||||
table.attach(self.entry_server_url, 1, 2, 0, 1, yoptions=gtk.FILL)
|
||||
|
||||
@@ -27,10 +27,7 @@ class Float(Integer):
|
||||
self.entry.set_text('')
|
||||
return False
|
||||
self.digits = field.attrs.get('digits', (16, 2))
|
||||
if isinstance(self.digits, str):
|
||||
digits = record.expr_eval(self.digits)
|
||||
else:
|
||||
digits = self.digits
|
||||
digits = record.expr_eval(self.digits)
|
||||
self.entry.set_width_chars(sum(digits))
|
||||
self.entry.set_text(locale.format('%.' + str(digits[1]) + 'f',
|
||||
field.get(record) or 0.0, True))
|
||||
@@ -54,10 +51,7 @@ class Float(Integer):
|
||||
if new_value in ('-', decimal_point):
|
||||
return
|
||||
|
||||
if isinstance(self.digits, str):
|
||||
digits = self.record.expr_eval(self.digits)
|
||||
else:
|
||||
digits = self.digits
|
||||
digits = self.record.expr_eval(self.digits)
|
||||
|
||||
try:
|
||||
locale.atof(new_value)
|
||||
|
||||
@@ -28,9 +28,7 @@ class ProgressBar(WidgetInterface):
|
||||
self.widget.set_fraction(0.0)
|
||||
return False
|
||||
value = float(field.get(record) or 0.0)
|
||||
digits = field.attrs.get('digits', (16, 2))
|
||||
if isinstance(self.digits, str):
|
||||
digits = record.expr_eval(self.digits)
|
||||
digits = record.expr_eval(field.attrs.get('digits', (16, 2)))
|
||||
self.widget.set_text(locale.format('%.' + str(digits[1]) + 'f',
|
||||
value, True))
|
||||
self.widget.set_fraction(value / 100.0)
|
||||
@@ -207,7 +207,8 @@ class ParserTree(ParserInterface):
|
||||
'float_time'):
|
||||
label = gtk.Label(node_attrs['sum'] + _(': '))
|
||||
label_sum = gtk.Label()
|
||||
if isinstance(fields[fname].attrs.get('digits'), str):
|
||||
if isinstance(fields[fname].attrs.get('digits'),
|
||||
basestring):
|
||||
digits = 2
|
||||
else:
|
||||
digits = fields[fname].attrs.get('digits', (16, 2))[1]
|
||||
@@ -456,18 +457,12 @@ class Float(Char):
|
||||
super(Float, self).setter(column, cell, store, iter)
|
||||
record = store.get_value(iter, 0)
|
||||
field = record[self.field_name]
|
||||
if isinstance(field.attrs.get('digits'), str):
|
||||
digits = record.expr_eval(field.attrs['digits'])
|
||||
else:
|
||||
digits = field.attrs.get('digits', (16, 2))
|
||||
digits = record.expr_eval(field.attrs.get('digits', (16, 2)))
|
||||
cell.digits = digits
|
||||
|
||||
def get_textual_value(self, record):
|
||||
field = record[self.field_name]
|
||||
if isinstance(field.attrs.get('digits'), str):
|
||||
digit = record.expr_eval(field.attrs['digits'])[1]
|
||||
else:
|
||||
digit = field.attrs.get('digits', (16, 2))[1]
|
||||
digit = record.expr_eval(field.attrs.get('digits', (16, 2)))[1]
|
||||
return locale.format('%.'+str(digit)+'f',
|
||||
record[self.field_name].get_client(record) or 0.0, True)
|
||||
|
||||
@@ -870,10 +865,7 @@ class ProgressBar(object):
|
||||
record = store.get_value(iter, 0)
|
||||
value = float(self.get_textual_value(record) or 0.0)
|
||||
cell.set_property('value', value)
|
||||
if isinstance(self.attrs.get('digits'), str):
|
||||
digit = record.expr_eval(self.attrs['digits'])[1]
|
||||
else:
|
||||
digit = self.attrs.get('digits', (16, 2))[1]
|
||||
digit = record.expr_eval(self.attrs.get('digits', (16, 2)))[1]
|
||||
text = locale.format('%.' + str(digit) + 'f', value, True)
|
||||
cell.set_property('text', text + '%')
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class Float(Integer):
|
||||
def __init__(self, name, attrs=None, context=None, on_change=None):
|
||||
super(Float, self).__init__(name, attrs=attrs, context=context,
|
||||
on_change=on_change)
|
||||
if isinstance(self.attrs.get('digits'), str):
|
||||
if isinstance(self.attrs.get('digits'), basestring):
|
||||
self.digits = (16, 2)
|
||||
else:
|
||||
self.digits = self.attrs.get('digits', (16, 2))
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
#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 xmlrpclib
|
||||
import json
|
||||
import ssl
|
||||
import httplib
|
||||
from decimal import Decimal
|
||||
import datetime
|
||||
import socket
|
||||
import gzip
|
||||
import StringIO
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
__all__ = ["ResponseError", "Fault", "ProtocolError", "Transport",
|
||||
"ServerProxy"]
|
||||
|
||||
|
||||
class ResponseError(xmlrpclib.ResponseError):
|
||||
pass
|
||||
|
||||
|
||||
class Fault(xmlrpclib.Fault):
|
||||
pass
|
||||
|
||||
|
||||
class ProtocolError(xmlrpclib.ProtocolError):
|
||||
pass
|
||||
|
||||
def object_hook(dct):
|
||||
if '__class__' in dct:
|
||||
if dct['__class__'] == 'datetime':
|
||||
return datetime.datetime(dct['year'], dct['month'], dct['day'],
|
||||
dct['hour'], dct['minute'], dct['second'])
|
||||
elif dct['__class__'] == 'date':
|
||||
return datetime.date(dct['year'], dct['month'], dct['day'])
|
||||
elif dct['__class__'] == 'Decimal':
|
||||
return Decimal(dct['decimal'])
|
||||
return dct
|
||||
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
|
||||
def default(self, obj):
|
||||
if isinstance(obj, datetime.date):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
return {'__class__': 'datetime',
|
||||
'year': obj.year,
|
||||
'month': obj.month,
|
||||
'day': obj.day,
|
||||
'hour': obj.hour,
|
||||
'minute': obj.minute,
|
||||
'second': obj.second,
|
||||
}
|
||||
return {'__class__': 'date',
|
||||
'year': obj.year,
|
||||
'month': obj.month,
|
||||
'day': obj.day,
|
||||
}
|
||||
elif isinstance(obj, Decimal):
|
||||
return {'__class__': 'Decimal',
|
||||
'decimal': str(obj),
|
||||
}
|
||||
return super(JSONEncoder, self).default(obj)
|
||||
|
||||
|
||||
class JSONParser(object):
|
||||
|
||||
def __init__(self, target):
|
||||
self.__targer = target
|
||||
|
||||
def feed(self, data):
|
||||
self.__targer.feed(data)
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
||||
class JSONUnmarshaller(object):
|
||||
data = ''
|
||||
|
||||
def feed(self, data):
|
||||
self.data += data
|
||||
|
||||
def close(self):
|
||||
return json.loads(self.data, object_hook=object_hook)
|
||||
|
||||
|
||||
class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport):
|
||||
|
||||
accept_gzip_encoding = True
|
||||
encode_threshold = 1400 # common MTU
|
||||
|
||||
def __init__(self, fingerprints=None, ca_certs=None):
|
||||
xmlrpclib.Transport.__init__(self)
|
||||
self.__connection = (None, None)
|
||||
self.__fingerprints = fingerprints
|
||||
self.__ca_certs = ca_certs
|
||||
|
||||
def getparser(self):
|
||||
target = JSONUnmarshaller()
|
||||
parser = JSONParser(target)
|
||||
return parser, target
|
||||
|
||||
def get_host_info(self, host):
|
||||
host, extra_headers, x509 = xmlrpclib.Transport.get_host_info(self, host)
|
||||
if extra_headers is None:
|
||||
extra_headers = []
|
||||
extra_headers.append(('Connection', 'keep-alive'))
|
||||
return host, extra_headers, x509
|
||||
|
||||
def send_content(self, connection, request_body):
|
||||
connection.putheader("Content-Type", "text/json")
|
||||
if (self.encode_threshold is not None and
|
||||
self.encode_threshold < len(request_body) and
|
||||
gzip):
|
||||
connection.putheader("Content-Encoding", "gzip")
|
||||
buffer = StringIO.StringIO()
|
||||
output = gzip.GzipFile(mode='wb', fileobj=buffer)
|
||||
output.write(request_body)
|
||||
output.close()
|
||||
buffer.seek(0)
|
||||
request_body = buffer.getvalue()
|
||||
connection.putheader("Content-Length", str(len(request_body)))
|
||||
connection.endheaders()
|
||||
if request_body:
|
||||
connection.send(request_body)
|
||||
|
||||
def make_connection(self, host):
|
||||
if self.__connection and host == self.__connection[0]:
|
||||
return self.__connection[1]
|
||||
fingerprint = None
|
||||
host, extra_headers, x509 = self.get_host_info(host)
|
||||
|
||||
ca_certs = self.__ca_certs
|
||||
cert_reqs = ssl.CERT_REQUIRED if ca_certs else ssl.CERT_NONE
|
||||
|
||||
|
||||
class HTTPSConnection(httplib.HTTPSConnection):
|
||||
def connect(self):
|
||||
sock = socket.create_connection((self.host, self.port),
|
||||
self.timeout)
|
||||
if self._tunnel_host:
|
||||
self.sock = sock
|
||||
self._tunnel()
|
||||
self.sock = ssl.wrap_socket(sock, self.key_file,
|
||||
self.cert_file, ca_certs=ca_certs, cert_reqs=cert_reqs)
|
||||
|
||||
self.__connection = host, HTTPSConnection(host)
|
||||
try:
|
||||
self.__connection[1].connect()
|
||||
sock = self.__connection[1].sock
|
||||
try:
|
||||
peercert = sock.getpeercert(True)
|
||||
except socket.error:
|
||||
peercert = None
|
||||
def format_hash(value):
|
||||
return reduce(lambda x, y: x + y[1].upper() +
|
||||
((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''),
|
||||
enumerate(value), '')
|
||||
fingerprint = format_hash(hashlib.sha1(peercert).hexdigest())
|
||||
except ssl.SSLError, e:
|
||||
self.__connection = host, httplib.HTTPConnection(host)
|
||||
if self.__fingerprints is not None:
|
||||
if host in self.__fingerprints:
|
||||
if self.__fingerprints[host] != fingerprint:
|
||||
self.close()
|
||||
raise ssl.SSLError('BadFingerprint')
|
||||
elif fingerprint:
|
||||
self.__fingerprints[host] = fingerprint
|
||||
return self.__connection[1]
|
||||
|
||||
if sys.version_info[:2] <= (2, 6):
|
||||
|
||||
def request(self, host, handler, request_body, verbose=0):
|
||||
h = self.make_connection(host)
|
||||
if verbose:
|
||||
h.set_debuglevel(1)
|
||||
|
||||
self.send_request(h, handler, request_body)
|
||||
self.send_host(h, host)
|
||||
self.send_user_agent(h)
|
||||
self.send_content(h, request_body)
|
||||
|
||||
response = h.getresponse()
|
||||
|
||||
if response.status != 200:
|
||||
raise ProtocolError(
|
||||
host + handler,
|
||||
response.status,
|
||||
response.reason,
|
||||
response.getheaders()
|
||||
)
|
||||
|
||||
self.verbose = verbose
|
||||
|
||||
try:
|
||||
sock = h._conn.sock
|
||||
except AttributeError:
|
||||
sock = None
|
||||
|
||||
if response.getheader("Content-Encoding", "") == "gzip":
|
||||
response = gzip.GzipFile(mode="rb",
|
||||
fileobj=StringIO.StringIO(response.read()))
|
||||
sock = None
|
||||
|
||||
return self._parse_response(response, sock)
|
||||
|
||||
def send_request(self, connection, handler, request_body):
|
||||
xmlrpclib.Transport.send_request(self, connection, handler,
|
||||
request_body)
|
||||
connection.putheader("Accept-Encoding", "gzip")
|
||||
|
||||
def close(self):
|
||||
if self.__connection[1]:
|
||||
self.__connection[1].close()
|
||||
self.__connection = (None, None)
|
||||
|
||||
|
||||
class ServerProxy(xmlrpclib.ServerProxy):
|
||||
__id = 0
|
||||
|
||||
def __init__(self, host, port, database='', verbose=0,
|
||||
fingerprints=None, ca_certs=None):
|
||||
self.__host = '%s:%s' % (host, port)
|
||||
self.__handler = '/' + database
|
||||
self.__transport = Transport(fingerprints, ca_certs)
|
||||
self.__verbose = verbose
|
||||
|
||||
def __request(self, methodname, params):
|
||||
self.__id += 1
|
||||
id_ = self.__id
|
||||
request = json.dumps({
|
||||
'id': id_,
|
||||
'method': methodname,
|
||||
'params': params,
|
||||
}, cls=JSONEncoder)
|
||||
|
||||
try:
|
||||
response = self.__transport.request(
|
||||
self.__host,
|
||||
self.__handler,
|
||||
request,
|
||||
verbose=self.__verbose
|
||||
)
|
||||
except socket.error, v:
|
||||
# trap 'Broken pipe'
|
||||
if v.args[0] != 32:
|
||||
raise
|
||||
# try one more time
|
||||
self.__transport.close()
|
||||
response = self.__transport.request(
|
||||
self.__host,
|
||||
self.__handler,
|
||||
request,
|
||||
verbose=self.__verbose
|
||||
)
|
||||
|
||||
if response['id'] != id_:
|
||||
raise ResponseError('Invalid response id (%s) excpected %s' %
|
||||
(response['id'], id_))
|
||||
if response.get('error'):
|
||||
raise Fault(*response['error'])
|
||||
return response['result']
|
||||
|
||||
def close(self):
|
||||
self.__transport.close()
|
||||
|
||||
@property
|
||||
def ssl(self):
|
||||
return isinstance(self.__transport.make_connection(self.__host),
|
||||
httplib.HTTPSConnection)
|
||||
@@ -1,255 +0,0 @@
|
||||
#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 socket
|
||||
# can't use/fall-back pickle due to different interface :-(
|
||||
import cPickle
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
except ImportError:
|
||||
import StringIO
|
||||
try:
|
||||
import ssl
|
||||
except ImportError:
|
||||
ssl = None
|
||||
import gzip
|
||||
try:
|
||||
import hashlib
|
||||
except ImportError:
|
||||
hashlib = None
|
||||
import sha
|
||||
import os
|
||||
|
||||
from tryton.exceptions import TrytonError, TrytonServerError
|
||||
|
||||
DNS_CACHE = {}
|
||||
MAX_SIZE = 999999999
|
||||
MAX_LENGHT = len(str(MAX_SIZE))
|
||||
CONNECT_TIMEOUT = 5
|
||||
TIMEOUT = 3600
|
||||
GZIP_THRESHOLD = 1400 # common MTU
|
||||
|
||||
_ALLOWED_MODULES = {'datetime': ['datetime', 'date'], 'decimal': ['Decimal']}
|
||||
|
||||
def checkfunction(module, klass):
|
||||
if module in _ALLOWED_MODULES and klass in _ALLOWED_MODULES[module]:
|
||||
mod = __import__(module, {}, {}, ['__all__'])
|
||||
_class = getattr(mod, klass)
|
||||
return _class
|
||||
raise ValueError('Not supported: %s/%s' % (module, klass))
|
||||
|
||||
|
||||
class PySocket:
|
||||
|
||||
def __init__(self, sock=None, fingerprints=None, ca_certs=None):
|
||||
self.sock = sock
|
||||
self.host = None
|
||||
self.hostname = None
|
||||
self.port = None
|
||||
self.ssl = False
|
||||
self.ssl_sock = None
|
||||
self.connected = False
|
||||
self.buffer = ''
|
||||
self.fingerprints = fingerprints
|
||||
if ca_certs and os.path.isfile(ca_certs):
|
||||
self.ca_certs = ca_certs
|
||||
else:
|
||||
self.ca_certs = None
|
||||
|
||||
def connect(self, host, port=False):
|
||||
if not port:
|
||||
buf = host.split('//')[1]
|
||||
host, port = buf.rsplit(':', 1)
|
||||
hostname = host
|
||||
if host in DNS_CACHE:
|
||||
host = DNS_CACHE[host]
|
||||
self.sock = None
|
||||
if socket.has_ipv6:
|
||||
try:
|
||||
socket.getaddrinfo(host, int(port), socket.AF_INET6)
|
||||
self.sock = socket.socket(socket.AF_INET6,
|
||||
socket.SOCK_STREAM)
|
||||
self.sock.settimeout(CONNECT_TIMEOUT)
|
||||
self.sock.connect((host, int(port)))
|
||||
except socket.error:
|
||||
self.sock = None
|
||||
if self.sock is None:
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.sock.settimeout(CONNECT_TIMEOUT)
|
||||
self.sock.connect((host, int(port)))
|
||||
DNS_CACHE[hostname], port = self.sock.getpeername()[:2]
|
||||
try:
|
||||
sock = None
|
||||
if socket.has_ipv6:
|
||||
try:
|
||||
socket.getaddrinfo(host, int(port), socket.AF_INET6)
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
sock.settimeout(CONNECT_TIMEOUT)
|
||||
sock.connect((host, int(port)))
|
||||
except socket.error:
|
||||
sock = None
|
||||
if sock is None:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(CONNECT_TIMEOUT)
|
||||
sock.connect((host, int(port)))
|
||||
if ssl:
|
||||
ssl_sock = ssl.wrap_socket(sock)
|
||||
self.ssl = True
|
||||
elif hasattr(socket, 'ssl'):
|
||||
ssl_sock = socket.ssl(sock)
|
||||
self.ssl = True
|
||||
except socket.error:
|
||||
pass
|
||||
self.sock.settimeout(TIMEOUT)
|
||||
fingerprint = None
|
||||
if self.ssl:
|
||||
if ssl:
|
||||
self.ssl_sock = ssl.wrap_socket(self.sock,
|
||||
ca_certs=self.ca_certs, cert_reqs=(self.ca_certs and
|
||||
ssl.CERT_REQUIRED or ssl.CERT_NONE))
|
||||
elif hasattr(socket, 'ssl'):
|
||||
self.ssl_sock = socket.ssl(self.sock, certfile=self.ca_certs)
|
||||
try:
|
||||
peercert = self.ssl_sock.getpeercert(True)
|
||||
except socket.error:
|
||||
peercert = None
|
||||
def format_hash(value):
|
||||
return reduce(lambda x, y: x + y[1].upper() +
|
||||
((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''),
|
||||
enumerate(value), '')
|
||||
if peercert and hashlib:
|
||||
fingerprint = format_hash(hashlib.sha1(peercert).hexdigest())
|
||||
elif peercert:
|
||||
fingerprint = format_hash(sha1.new(peercert).hexdigest())
|
||||
self.host = host
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
self.connected = True
|
||||
self.buffer = ''
|
||||
if self.fingerprints is not None:
|
||||
key = (self.hostname, str(self.port))
|
||||
if key in self.fingerprints:
|
||||
if self.fingerprints[key] != fingerprint:
|
||||
self.disconnect()
|
||||
raise TrytonError('BadFingerprint')
|
||||
elif fingerprint:
|
||||
self.fingerprints[key] = fingerprint
|
||||
|
||||
def disconnect(self):
|
||||
try:
|
||||
sock = self.sock
|
||||
if self.ssl:
|
||||
sock = self.ssl_sock
|
||||
try:
|
||||
shutdown_value = 2
|
||||
if hasattr(socket, 'SHUT_RDWR'):
|
||||
shutdown_value = socket.SHUT_RDWR
|
||||
if hasattr(sock, 'sock_shutdown'):
|
||||
sock.sock_shutdown(shutdown_value)
|
||||
else:
|
||||
sock.shutdown(shutdown_value)
|
||||
except socket.error:
|
||||
pass
|
||||
sock.close()
|
||||
except socket.error:
|
||||
pass
|
||||
self.sock = None
|
||||
self.ssl = False
|
||||
self.ssl_sock = None
|
||||
self.connected = False
|
||||
self.buffer = ''
|
||||
|
||||
def reconnect(self):
|
||||
if self.hostname and self.port:
|
||||
self.disconnect()
|
||||
self.connect(self.hostname, self.port)
|
||||
|
||||
def send(self, msg, exception=False, traceback=None):
|
||||
msg = cPickle.dumps([msg, traceback], protocol=2)
|
||||
gzip_p = False
|
||||
if len(msg) > GZIP_THRESHOLD:
|
||||
buffer = StringIO.StringIO()
|
||||
output = gzip.GzipFile(mode='wb', fileobj=buffer)
|
||||
output.write(msg)
|
||||
output.close()
|
||||
buffer.seek(0)
|
||||
msg = buffer.getvalue()
|
||||
gzip_p = True
|
||||
size = len(msg)
|
||||
msg = str(size) + ' ' + (exception and "1" or "0") \
|
||||
+ (gzip_p and "1" or "0") + msg
|
||||
size = len(msg)
|
||||
|
||||
if self.ssl:
|
||||
totalsent = 0
|
||||
while totalsent < size:
|
||||
sent = self.ssl_sock.write(msg[totalsent:])
|
||||
if sent == 0:
|
||||
raise RuntimeError("socket connection broken")
|
||||
totalsent = totalsent + sent
|
||||
else:
|
||||
self.sock.sendall(msg)
|
||||
|
||||
def receive(self):
|
||||
buf = self.buffer
|
||||
L = []
|
||||
size_remaining = MAX_LENGHT
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, 4096)
|
||||
if self.ssl:
|
||||
chunk = self.ssl_sock.read(chunk_size)
|
||||
else:
|
||||
chunk = self.sock.recv(chunk_size)
|
||||
if chunk == '':
|
||||
raise RuntimeError("socket connection broken")
|
||||
L.append(chunk)
|
||||
size_remaining -= len(chunk)
|
||||
if ' ' in chunk:
|
||||
break
|
||||
if size_remaining < 0:
|
||||
raise RuntimeError("socket connection broken")
|
||||
buf += ''.join(L)
|
||||
size, msg = buf.split(' ', 1)
|
||||
size = int(size)
|
||||
if size > MAX_SIZE:
|
||||
raise RuntimeError("socket connection broken")
|
||||
while len(msg) < 2:
|
||||
chunk_size = min(size + 2, 4096)
|
||||
if self.ssl:
|
||||
msg += self.ssl_sock.read(chunk_size)
|
||||
else:
|
||||
msg += self.sock.recv(chunk_size)
|
||||
if msg == '':
|
||||
raise RuntimeError("socket connection broken")
|
||||
exception = msg[0] != "0"
|
||||
gzip_p = msg[1] != "0"
|
||||
L = [msg[2:]]
|
||||
size_remaining = size - len(L[0])
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, 4096)
|
||||
if self.ssl:
|
||||
chunk = self.ssl_sock.read(chunk_size)
|
||||
else:
|
||||
chunk = self.sock.recv(chunk_size)
|
||||
if chunk == '':
|
||||
raise RuntimeError("socket connection broken")
|
||||
L.append(chunk)
|
||||
size_remaining -= len(chunk)
|
||||
msg = ''.join(L)
|
||||
if len(msg) > size:
|
||||
self.buffer = msg[size:]
|
||||
msg = msg[:size]
|
||||
else:
|
||||
self.buffer = ''
|
||||
msgio = StringIO.StringIO(msg)
|
||||
if gzip_p:
|
||||
output = gzip.GzipFile(mode='r', fileobj=msgio)
|
||||
msgio = StringIO.StringIO(output.read(-1))
|
||||
output.close()
|
||||
unpickler = cPickle.Unpickler(msgio)
|
||||
# cPickle mechanism to import instances (pickle differs here)
|
||||
unpickler.find_global = checkfunction
|
||||
res = unpickler.load()
|
||||
if exception:
|
||||
raise TrytonServerError(*(list(res[0]) + [res[1]]))
|
||||
else:
|
||||
return res[0]
|
||||
+68
-136
@@ -1,57 +1,43 @@
|
||||
#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 itertools
|
||||
import pysocket
|
||||
import logging
|
||||
import socket
|
||||
import os
|
||||
from threading import Semaphore
|
||||
from functools import partial
|
||||
from tryton.jsonrpc import ServerProxy, Fault
|
||||
from tryton.fingerprints import Fingerprints
|
||||
from tryton.config import get_config_dir
|
||||
from tryton.ipc import Server as IPCServer
|
||||
from tryton.exceptions import TrytonServerError
|
||||
|
||||
_SOCK = None
|
||||
CONNECTION = None
|
||||
_USER = None
|
||||
_USERNAME = ''
|
||||
_SESSION = ''
|
||||
_HOST = ''
|
||||
_PORT = None
|
||||
_DATABASE = ''
|
||||
CONTEXT = {}
|
||||
_VIEW_CACHE = {}
|
||||
TIMEZONE = 'utc'
|
||||
SECURE = False
|
||||
_SEMAPHORE = Semaphore()
|
||||
_CA_CERTS = os.path.join(get_config_dir(), 'ca_certs')
|
||||
if not os.path.isfile(_CA_CERTS):
|
||||
_CA_CERTS = None
|
||||
_FINGERPRINTS = Fingerprints()
|
||||
|
||||
ServerProxy = partial(ServerProxy, fingerprints=_FINGERPRINTS, ca_certs=_CA_CERTS)
|
||||
|
||||
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(fingerprints=Fingerprints(),
|
||||
ca_certs=_CA_CERTS)
|
||||
if not _SOCK.connected:
|
||||
_SOCK.connect(host, port)
|
||||
args = (None, None, None, 'common', 'db', 'list')
|
||||
logging.getLogger('rpc.request').info(repr(args))
|
||||
try:
|
||||
_SOCK.send(args)
|
||||
except socket.error, exception:
|
||||
if exception.args[0] == 32:
|
||||
_SOCK.reconnect()
|
||||
_SOCK.send(args)
|
||||
else:
|
||||
raise
|
||||
res = _SOCK.receive()
|
||||
SECURE = _SOCK.ssl
|
||||
finally:
|
||||
_SEMAPHORE.release()
|
||||
logging.getLogger('rpc.result').debug(repr(res))
|
||||
return res
|
||||
except TrytonServerError, exception:
|
||||
connection = ServerProxy(host, port)
|
||||
logging.getLogger('rpc.request').info('common.db.list(None, None)')
|
||||
result = connection.common.db.list(None, None)
|
||||
logging.getLogger('rpc.result').debug(repr(result))
|
||||
return result
|
||||
except Fault, exception:
|
||||
if exception.args[0] == 'AccessDenied':
|
||||
raise
|
||||
else:
|
||||
@@ -59,137 +45,90 @@ def db_list(host, port):
|
||||
return None
|
||||
|
||||
def db_exec(host, port, method, *args):
|
||||
global _SOCK, SECURE
|
||||
_SEMAPHORE.acquire()
|
||||
try:
|
||||
if _SOCK and (_SOCK.hostname != host or _SOCK.port != port):
|
||||
_SOCK.disconnect()
|
||||
if _SOCK is None:
|
||||
_SOCK= pysocket.PySocket(fingerprints=Fingerprints(),
|
||||
ca_certs=_CA_CERTS)
|
||||
if not _SOCK.connected:
|
||||
_SOCK.connect(host, port)
|
||||
args = (None, None, None, 'common', 'db', method) + args
|
||||
logging.getLogger('rpc.request').info(repr(args))
|
||||
try:
|
||||
_SOCK.send(args)
|
||||
except socket.error, exception:
|
||||
if exception.args[0] == 32:
|
||||
_SOCK.reconnect()
|
||||
_SOCK.send(args)
|
||||
else:
|
||||
raise
|
||||
res = _SOCK.receive()
|
||||
SECURE = _SOCK.ssl
|
||||
finally:
|
||||
_SEMAPHORE.release()
|
||||
logging.getLogger('rpc.result').debug(repr(res))
|
||||
return res
|
||||
connection = ServerProxy(host, port)
|
||||
logging.getLogger('rpc.request').info('common.db.%s(None, None, %s)' %
|
||||
(method, args))
|
||||
result = getattr(connection.common.db, method)(None, None, *args)
|
||||
logging.getLogger('rpc.result').debug(repr(result))
|
||||
return result
|
||||
|
||||
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(fingerprints=Fingerprints(),
|
||||
ca_certs=_CA_CERTS)
|
||||
if not _SOCK.connected:
|
||||
_SOCK.connect(host, port)
|
||||
args = (None, None, None, 'common', None, 'version')
|
||||
logging.getLogger('rpc.request').info(repr(args))
|
||||
try:
|
||||
_SOCK.send(args)
|
||||
except socket.error, exception:
|
||||
if exception.args[0] == 32:
|
||||
_SOCK.reconnect()
|
||||
_SOCK.send(args)
|
||||
else:
|
||||
raise
|
||||
res = _SOCK.receive()
|
||||
SECURE = _SOCK.ssl
|
||||
finally:
|
||||
_SEMAPHORE.release()
|
||||
logging.getLogger('rpc.result').debug(repr(res))
|
||||
return res
|
||||
except (TrytonServerError, socket.error):
|
||||
connection = ServerProxy(host, port)
|
||||
logging.getLogger('rpc.request').info(
|
||||
'common.server.version(None, None)')
|
||||
result = connection.common.server.version(None, None)
|
||||
logging.getLogger('rpc.result').debug(repr(result))
|
||||
return result
|
||||
except (Fault, socket.error):
|
||||
logging.getLogger('rpc.result').debug(repr(None))
|
||||
return None
|
||||
|
||||
def login(username, password, host, port, database):
|
||||
global _SOCK, _USER, _USERNAME, _SESSION, _DATABASE, _VIEW_CACHE, SECURE
|
||||
global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE, _VIEW_CACHE
|
||||
_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(fingerprints=Fingerprints(),
|
||||
ca_certs=_CA_CERTS)
|
||||
if not _SOCK.connected:
|
||||
_SOCK.connect(host, port)
|
||||
args = (database, username, password, 'common', 'db', 'login')
|
||||
logging.getLogger('rpc.request').info(repr(args))
|
||||
_SOCK.send(args)
|
||||
res = _SOCK.receive()
|
||||
logging.getLogger('rpc.result').debug(repr(res))
|
||||
connection = ServerProxy(host, port, database)
|
||||
if str(connection) != str(CONNECTION):
|
||||
if CONNECTION:
|
||||
CONNECTION.close()
|
||||
CONNECTION = connection
|
||||
else:
|
||||
connection = CONNECTION
|
||||
logging.getLogger('rpc.request').info('common.db.login(%s, %s)' %
|
||||
(username, 'x' * 10))
|
||||
result = connection.common.db.login(username, password)
|
||||
logging.getLogger('rpc.result').debug(repr(result))
|
||||
finally:
|
||||
_SEMAPHORE.release()
|
||||
except (socket.error, RuntimeError):
|
||||
try:
|
||||
_SOCK.reconnect()
|
||||
except (socket.error, RuntimeError):
|
||||
pass
|
||||
except socket.error:
|
||||
_USER = None
|
||||
_SESSION = ''
|
||||
return -1
|
||||
if not res:
|
||||
if not result:
|
||||
_USER = None
|
||||
_SESSION = ''
|
||||
return -2
|
||||
_USER = res[0]
|
||||
_USER = result[0]
|
||||
_USERNAME = username
|
||||
_SESSION = res[1]
|
||||
_SESSION = result[1]
|
||||
_HOST = host
|
||||
_PORT = port
|
||||
_DATABASE = database
|
||||
SECURE = _SOCK.ssl
|
||||
IPCServer(host, port, database).run()
|
||||
return 1
|
||||
|
||||
def logout():
|
||||
global _SOCK, _USER, _USERNAME, _SESSION, _DATABASE, _VIEW_CACHE, SECURE
|
||||
global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE, _VIEW_CACHE
|
||||
if IPCServer.instance:
|
||||
IPCServer.instance.stop()
|
||||
if _SOCK and _USER:
|
||||
if CONNECTION is not None:
|
||||
_SEMAPHORE.acquire()
|
||||
try:
|
||||
args = (_DATABASE, _USER, _SESSION, 'common', 'db', 'logout')
|
||||
logging.getLogger('rpc.request').info(repr(args))
|
||||
_SOCK.sock.settimeout(pysocket.CONNECT_TIMEOUT)
|
||||
_SOCK.send(args)
|
||||
res = _SOCK.receive()
|
||||
logging.getLogger('rpc.result').debug(repr(res))
|
||||
except socket.error:
|
||||
logging.getLogger('rpc.request').info('common.db.logout(%s, %s)' %
|
||||
(_USER, _SESSION))
|
||||
CONNECTION.common.db.logout(_USER, _SESSION)
|
||||
except (Fault, socket.error):
|
||||
pass
|
||||
finally:
|
||||
_SEMAPHORE.release()
|
||||
_SOCK.disconnect()
|
||||
_SOCK = None
|
||||
CONNECTION.close()
|
||||
CONNECTION = None
|
||||
_USER = None
|
||||
_USERNAME = ''
|
||||
_SESSION = ''
|
||||
_HOST = ''
|
||||
_PORT = None
|
||||
_DATABASE = ''
|
||||
_VIEW_CACHE = {}
|
||||
SECURE = False
|
||||
|
||||
def context_reload():
|
||||
global CONTEXT, TIMEZONE
|
||||
global CONTEXT, TIMEZONE, _HOST, _PORT
|
||||
try:
|
||||
context = execute('model', 'res.user', 'get_preferences', True, {})
|
||||
except TrytonServerError:
|
||||
except Fault:
|
||||
return
|
||||
CONTEXT = {}
|
||||
for i in context:
|
||||
@@ -197,15 +136,15 @@ def context_reload():
|
||||
CONTEXT[i] = value
|
||||
if i == 'timezone':
|
||||
try:
|
||||
TIMEZONE = execute('common', None, 'timezone_get')
|
||||
except TrytonServerError:
|
||||
connection = ServerProxy(_HOST, _PORT)
|
||||
TIMEZONE = connection.common.server.timezone_get(None, None)
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
def _execute(blocking, *args):
|
||||
global _SOCK, _DATABASE, _USER, _SESSION
|
||||
if not _SOCK or not _SOCK.connected:
|
||||
global CONNECTION, _USER, _SESSION
|
||||
if CONNECTION is None:
|
||||
raise TrytonServerError('NotLogged')
|
||||
logging.getLogger('rpc.request').info(repr((args)))
|
||||
key = False
|
||||
if args[2] == 'fields_view_get':
|
||||
args, ctx = args[:-1], args[-1]
|
||||
@@ -223,17 +162,10 @@ def _execute(blocking, *args):
|
||||
if not res:
|
||||
return
|
||||
try:
|
||||
try:
|
||||
_SOCK.send((_DATABASE, _USER, _SESSION) + args)
|
||||
result = _SOCK.receive()
|
||||
except (socket.error, RuntimeError):
|
||||
try:
|
||||
_SOCK.reconnect()
|
||||
_SOCK.send((_DATABASE, _USER, _SESSION) + args)
|
||||
result = _SOCK.receive()
|
||||
except (socket.error, RuntimeError):
|
||||
_SOCK.reconnect()
|
||||
raise
|
||||
name = '.'.join(args[:3])
|
||||
args = (_USER, _SESSION) + args[3:]
|
||||
logging.getLogger('rpc.request').info('%s%s' % (name, args))
|
||||
result = getattr(CONNECTION, name)(*args)
|
||||
finally:
|
||||
_SEMAPHORE.release()
|
||||
if key:
|
||||
|
||||
Reference in new issue
Block a user