1 from xml.dom import minidom
2 from xml.sax import handler, make_parser, saxutils
3 from osrf.json import *
4 from osrf.net_obj import *
6 import urllib, urllib2, sys, re
11 def __init__(self, service, method, params=[]):
12 self.service = service
17 def setPath(self, path):
21 params = self.buildPOSTParams()
22 request = urllib2.Request(self.buildURL(), data=params)
25 response =urllib2.urlopen(request)
26 except urllib2.HTTPError, e:
28 sys.stderr.write('%s => %s?%s\n' % (unicode(e), self.buildURL(), params))
31 return self.handleResponse(response)
33 def buildPOSTParams(self):
35 params = urllib.urlencode({
36 'service': self.service,
37 'method': self.method,
38 'format': self.getFormat(),
39 'input_format': self.getInputFormat()
43 params += '¶m=%s' % urllib.quote(self.encodeParam(p), "'/")
46 def setDefaultHost(host):
49 setDefaultHost = staticmethod(setDefaultHost)
52 return 'http://%s/%s' % (defaultHost, self.path)
54 class JSONGatewayRequest(GatewayRequest):
55 def __init__(self, service, method, *params):
56 GatewayRequest.__init__(self, service, method, list(params))
61 def getInputFormat(self):
62 return self.getFormat()
64 def handleResponse(self, response):
66 obj = osrfJSONToObject(s)
67 if obj['status'] != 200:
68 sys.stderr.write('JSON gateway returned status %d:\n%s\n' % (obj['status'], s))
71 # the gateway wraps responses in an array to handle streaming data
72 # if there is only one item in the array, it (probably) wasn't a streaming request
74 if len(p) > 1: return p
77 def encodeParam(self, param):
78 return osrfObjectToJSON(param)
80 class XMLGatewayRequest(GatewayRequest):
82 def __init__(self, service, method, *params):
83 GatewayRequest.__init__(self, service, method, list(params))
88 def getInputFormat(self):
89 return self.getFormat()
91 def handleResponse(self, response):
92 handler = XMLGatewayParser()
93 parser = make_parser()
94 parser.setContentHandler(handler)
96 parser.parse(response)
98 osrfLogErr('Error parsing gateway XML: %s' % unicode(e))
101 return handler.getResult()
103 def encodeParam(self, param):
104 return osrfObjectToXML(param);
106 class XMLGatewayParser(handler.ContentHandler):
112 self.posStack = [] # for tracking array-based hinted object indices
114 # true if we are parsing an element that may have character data
115 self.charsPending = 0
120 def __getAttr(self, attrs, name):
121 for (k, v) in attrs.items():
126 def startElement(self, name, attrs):
128 if self.charsPending:
129 # we just read a 'string' or 'number' element that resulted
130 # in no text data. Appaned a None object
131 self.appendChild(None)
134 self.appendChild(None)
137 if name == 'string' or name == 'number':
138 self.charsPending = True
141 if name == 'element': # this is an object item wrapper
142 self.keyStack.append(self.__getAttr(attrs, 'key'))
145 hint = self.__getAttr(attrs, 'class_hint')
147 obj = osrfNewObjectFromHint(hint)
148 self.appendChild(obj)
149 self.objStack.append(obj)
151 self.posStack.append(0)
156 self.appendChild(obj)
157 self.objStack.append(obj)
162 self.appendChild(obj)
163 self.objStack.append(obj)
166 if name == 'boolean':
167 self.appendChild((self.__getAttr(attrs, 'value') == 'true'))
171 def appendChild(self, child):
173 if self.result == None:
176 if not self.objStack: return;
178 parent = self.objStack[len(self.objStack)-1]
180 if isinstance(parent, list):
183 if isinstance(parent, dict):
184 parent[self.keyStack.pop()] = child
186 if isinstance(parent, osrfNetworkObject):
188 if parent.getRegistry().wireProtocol == 'array':
189 keys = parent.getRegistry().keys
190 i = self.posStack.pop()
193 self.posStack.append(i+1)
195 key = self.keyStack.pop()
197 parent.setField(key, child)
199 def endElement(self, name):
200 if name == 'array' or name == 'object':
203 def characters(self, chars):
204 self.charsPending = False
205 self.appendChild(urllib.unquote_plus(chars))