1
2
3
4
5
6
7 """ JSONService is a module providing JSON RPC Client side proxying.
8 """
9
10 import sys
11 from HTTPRequest import HTTPRequest
12
13 try:
14
15 from json import dumps, loads
16 except ImportError:
17
18 from simplejson import dumps, loads
19
22
23 __requestID = 0
24 __requestIDPrefix = 'ID'
25 __lastRequestID = None
42
43
45 content_type = 'application/json-rpc'
46 accept = 'application/json-rpc'
47
48 - def __init__(self, url, handler=None, headers=None):
49 """
50 Create a JSON remote service object. The url is the URL that will
51 receive POST data with the JSON request. See the JSON-RPC spec for
52 more information.
53
54 The handler object should implement::
55
56 onRemoteResponse(value, requestInfo)
57
58 to accept the return value of the remote method, and::
59
60 onRemoteError(code, error_dict, requestInfo)
61 code = http-code or 0
62 error_dict is an jsonrpc 2.0 error dict:
63 {
64 'code': jsonrpc-error-code (integer) ,
65 'message': jsonrpc-error-message (string) ,
66 'data' : extra-error-data
67 }
68
69 to handle errors.
70 """
71 self.url = url
72 self.handler = handler
73 self.headers = headers if headers is not None else {}
74 if not self.headers.get("Accept"):
75 self.headers["Accept"] = self.accept
76
77 - def callMethod(self, method, params, handler = None):
78 if handler is None:
79 handler = self.handler
80
81 if handler is None:
82 return self.sendNotify(method, params)
83 else:
84 return self.sendRequest(method, params, handler)
85
88
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 msg = {"jsonrpc": "2.0",
117 "version": "1.1",
118 "method": method,
119 "params": params
120 }
121 msg_data = dumps(msg)
122 if not HTTPRequest().asyncPost(self.url, msg_data, self,
123 False, self.content_type,
124 self.headers):
125 return -1
126 return 1
127
129 id = nextRequestID()
130 msg = {"jsonrpc": "2.0",
131 "id": id,
132 "method": method,
133 "params": params
134 }
135 msg_data = dumps(msg)
136
137 request_info = JSONRequestInfo(id, method, handler)
138 if not HTTPRequest().asyncPost(self.url, msg_data,
139 JSONResponseTextHandler(request_info),
140 False, self.content_type,
141 self.headers):
142 return -1
143 return id
144
145
147 - def __init__(self, id, method, handler):
148 self.id = id
149 self.method = method
150 self.handler = handler
151
153 """ creates an object by looking for __jsonclass__ hint,
154 loading the class from that and then constructing an
155 object from the rest of the dictionary as kwargs
156 """
157 clsname = items.pop('__jsonclass__', None)
158 if not clsname:
159 return items
160 clsname = clsname[0]
161 dot = clsname.rfind('.')
162 modulename = clsname[:dot]
163 clsname = clsname[dot+1:]
164 vars = {}
165 exec "from %s import %s as kls" % (modulename, clsname) in vars
166 kls = vars['kls']
167 vars = {}
168 for (k, v) in items.items():
169 vars[str(k)] = v
170 return kls(**vars)
171
174
176 - def __init__(self, request):
177 self.request = request
178
179 - def onCompletion(self, json_str):
180 try:
181 response = _decode_response(json_str)
182 except:
183
184 error = dict(
185 code=-32700,
186 message="Parse error while decoding response",
187 data=None,
188 )
189 self.request.handler.onRemoteError(0, error, self.request)
190 return
191
192 if not response:
193 error = dict(
194 code=-32603,
195 message="Empty Response",
196 data=None,
197 )
198 self.request.handler.onRemoteError(0, error, self.request)
199 elif response.get("error"):
200 error = response["error"]
201 jsonrpc = response.get("jsonrpc")
202 code = error.get("code", 0)
203 message = error.get("message", error)
204 data = error.get("data")
205 if not jsonrpc:
206 jsonrpc = response.get("version", "1.0")
207 if jsonrpc == "1.0":
208 message = error
209 else:
210 data = error.get("error")
211 error = dict(
212 code=code,
213 message=message,
214 data=data,
215 )
216 self.request.handler.onRemoteError(0, error, self.request)
217 elif "result" in response:
218 self.request.handler.onRemoteResponse(response["result"],
219 self.request)
220 else:
221 error = dict(
222 code=-32603,
223 message="No result or error in response",
224 data=response,
225 )
226 self.request.handler.onRemoteError(0, error, self.request)
227
228 - def onError(self, error_str, error_code):
229 error = dict(
230 code=error_code,
231 message=error_str,
232 data=None,
233 )
234 self.request.handler.onRemoteError(error_code, error, self.request)
235
237 - def __init__(self, serviceURL, serviceName=None, headers=None):
238 JSONService.__init__(self, serviceURL, headers=headers)
239 self.__serviceName = serviceName
240
242 if isinstance(params, tuple):
243 params = list(params)
244 if params and hasattr(params[0], "onRemoteResponse"):
245 handler = params.pop(0)
246 elif params and hasattr(params[-1], "onRemoteResponse"):
247 handler = params.pop()
248 else:
249 handler = None
250 if kwargs:
251 if params:
252 if not isinstance(params, dict):
253 raise JSONServiceError("Cannot mix positional and keyword arguments")
254 params.update(kwargs)
255 else:
256 params = kwargs
257 if handler is not None:
258 return JSONService.sendRequest(self, self.__serviceName,
259 params, handler)
260 else:
261 return JSONService.sendNotify(self, self.__serviceName, params)
262
263
265 - def __init__(self, url, methods=None, headers=None):
266 self._serviceURL = url
267 self.methods = methods
268 self.headers = {} if headers is None else headers
269
270 JSONService.__init__(self, url, headers=self.headers)
271 self._registerMethods(methods)
272
274 if methods:
275 for method in methods:
276 setattr(self,
277 method,
278 getattr(ServiceProxy(self._serviceURL, method,
279 headers=self.headers),
280 '__call__')
281 )
282
283
284
285
286
287
288
289
290
291