Merge lp:~akfypznt56ld-mike/openerp-client-lib/dnservices-release into lp:openerp-client-lib

Proposed by Mike
Status: Needs review
Proposed branch: lp:~akfypznt56ld-mike/openerp-client-lib/dnservices-release
Merge into: lp:openerp-client-lib
Diff against target: 192 lines (+174/-0) (has conflicts)
1 file modified
openerplib/main.py (+174/-0)
Text conflict in openerplib/main.py
To merge this branch: bzr merge lp:~akfypznt56ld-mike/openerp-client-lib/dnservices-release
Reviewer Review Type Date Requested Status
Nicolas Vanhoren (OpenERP) Pending
Review via email: mp+91794@code.launchpad.net

Description of the change

Added exec_workflow and report functions to Module class
Added global_unpickle to handle NetRPC OpenERP exceptions

To post a comment you must log in.

Unmerged revisions

37. By Mike

Added exec_workflow and report functions, fixed exception handling causing Global Unpickling error

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerplib/main.py'
2--- openerplib/main.py 2012-01-09 09:19:06 +0000
3+++ openerplib/main.py 2012-02-07 10:53:18 +0000
4@@ -89,7 +89,145 @@
5
6 def __init__(self, hostname, port=8069):
7 super(XmlRPCSConnector, self).__init__(hostname, port)
8+<<<<<<< TREE
9 self.url = 'https://%s:%d/xmlrpc' % (hostname, port)
10+=======
11+ self.url = 'https://%s:%d/xmlrpc' % (self.hostname, self.port)
12+
13+class NetRPC_Exception(Exception):
14+ """
15+ Exception for NetRPC errors.
16+ """
17+ def __init__(self, faultCode, faultString):
18+ self.faultCode = faultCode
19+ self.faultString = faultString
20+ self.args = (faultCode, faultString)
21+
22+def global_unpickle(modulename, classname):
23+ if classname == 'Exception':
24+ return Exception
25+
26+ _logger.error("Unknown or unhandled pickled instance: %s.%s" % (modulename, classname))
27+
28+
29+class NetRPC(object):
30+ """
31+ Low level class for NetRPC protocol.
32+ """
33+ def __init__(self, sock=None):
34+ if sock is None:
35+ self.sock = socket.socket(
36+ socket.AF_INET, socket.SOCK_STREAM)
37+ else:
38+ self.sock = sock
39+ self.sock.settimeout(120)
40+ def connect(self, host, port=False):
41+ if not port:
42+ buf = host.split('//')[1]
43+ host, port = buf.split(':')
44+ self.sock.connect((host, int(port)))
45+
46+ def disconnect(self):
47+ self.sock.shutdown(socket.SHUT_RDWR)
48+ self.sock.close()
49+
50+ def mysend(self, msg, exception=False, traceback=None):
51+ msg = pickle.dumps([msg,traceback])
52+ size = len(msg)
53+ self.sock.send('%8d' % size)
54+ self.sock.send(exception and "1" or "0")
55+ totalsent = 0
56+ while totalsent < size:
57+ sent = self.sock.send(msg[totalsent:])
58+ if sent == 0:
59+ raise RuntimeError, "socket connection broken"
60+ totalsent = totalsent + sent
61+
62+ def myreceive(self):
63+ buf=''
64+ while len(buf) < 8:
65+ chunk = self.sock.recv(8 - len(buf))
66+ if chunk == '':
67+ raise RuntimeError, "socket connection broken"
68+ buf += chunk
69+ size = int(buf)
70+ buf = self.sock.recv(1)
71+ if buf != "0":
72+ exception = buf
73+ else:
74+ exception = False
75+ msg = ''
76+ while len(msg) < size:
77+ chunk = self.sock.recv(size-len(msg))
78+ if chunk == '':
79+ raise RuntimeError, "socket connection broken"
80+ msg = msg + chunk
81+
82+
83+ msgio = StringIO.StringIO(msg)
84+
85+ unpickler = pickle.Unpickler(msgio)
86+ unpickler.find_global = global_unpickle
87+
88+ res = unpickler.load()
89+
90+ if isinstance(res[0],Exception):
91+ if exception:
92+ raise NetRPC_Exception(str(res[0]), str(res[1]))
93+ raise res[0]
94+ else:
95+ return res[0]
96+
97+class NetRPCConnector(Connector):
98+ """
99+ A type of connector that uses the NetRPC protocol.
100+ """
101+
102+ PROTOCOL = 'netrpc'
103+
104+ __logger = _getChildLogger(_logger, 'connector.netrpc')
105+
106+ def __init__(self, hostname, port=8070):
107+ """
108+ Initialize by specifying the hostname and the port.
109+ :param hostname: The hostname of the computer holding the instance of OpenERP.
110+ :param port: The port used by the OpenERP instance for NetRPC (default to 8070).
111+ """
112+ Connector.__init__(self, hostname, port)
113+
114+ def send(self, service_name, method, *args):
115+ socket = NetRPC()
116+ socket.connect(self.hostname, self.port)
117+ socket.mysend((service_name, method, )+args)
118+ result = socket.myreceive()
119+ socket.disconnect()
120+ return result
121+
122+class LocalConnector(Connector):
123+ """
124+ A type of connector that uses the XMLRPC protocol.
125+ """
126+ PROTOCOL = 'local'
127+
128+ __logger = _getChildLogger(_logger, 'connector.local')
129+
130+ def __init__(self):
131+ pass
132+
133+ def send(self, service_name, method, *args):
134+ import openerp
135+ # TODO Exception handling
136+ # This will be changed to be xmlrpc compatible
137+ # OpenERPWarning code 1
138+ # OpenERPException code 2
139+ try:
140+ result = openerp.netsvc.dispatch_rpc(service_name, method, args)
141+ except:
142+ exc_type, exc_value, exc_tb = sys.exc_info()
143+ fault = xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value))
144+ raise fault
145+ return result
146+>>>>>>> MERGE-SOURCE
147
148 class Service(object):
149 """
150@@ -275,6 +413,42 @@
151 records = self.read(record_ids, fields or [], context or {})
152 return records
153
154+ def exec_workflow(self, method, *args):
155+ self.connection.check_login(False)
156+ self.__logger.debug(args)
157+ result = self.connection.get_service('object').exec_workflow(
158+ self.connection.database,
159+ self.connection.user_id,
160+ self.connection.password,
161+ self.model_name,
162+ method,
163+ *args)
164+ self.__logger.debug('result: %r', result)
165+ return result
166+
167+ def report(self, *args):
168+ self.connection.check_login(False)
169+ self.__logger.debug(args)
170+ result = self.connection.get_service('report').report(
171+ self.connection.database,
172+ self.connection.user_id,
173+ self.connection.password,
174+ self.model_name,
175+ *args)
176+ self.__logger.debug('result: %r', result)
177+
178+ return result
179+
180+ def report_get(self, *args):
181+ self.connection.check_login(False)
182+ self.__logger.debug(args)
183+ result = self.connection.get_service('report').report_get(
184+ self.connection.database,
185+ self.connection.user_id,
186+ self.connection.password,
187+ *args)
188+ return result
189+
190 def get_connector(hostname=None, protocol="xmlrpc", port="auto"):
191 """
192 A shortcut method to easily create a connector to a remote server using XMLRPC.

Subscribers

People subscribed via source and target branches