1 from xml.dom import minidom
2 from xml.sax import handler, make_parser, saxutils
5 import urllib, urllib2, sys, re
10 def __init__(self, service, method, params=[]):
11 self.service = service
16 def setPath(self, path):
20 params = self.buildPOSTParams()
21 request = urllib2.Request(self.buildURL(), data=params)
24 response =urllib2.urlopen(request)
25 except urllib2.HTTPError, e:
27 sys.stderr.write('%s => %s?%s\n' % (str(e), self.buildURL(), params))
30 return self.handleResponse(response)
32 def buildPOSTParams(self):
34 params = urllib.urlencode({
35 'service': self.service,
36 'method': self.method,
37 'format': self.getFormat(),
38 'input_format': self.getInputFormat()
42 params += '¶m=%s' % urllib.quote(self.encodeParam(p), "'/")
45 def setDefaultHost(host):
48 setDefaultHost = staticmethod(setDefaultHost)
51 return 'http://%s/%s' % (defaultHost, self.path)
53 class JSONGatewayRequest(GatewayRequest):
54 def __init__(self, service, method, *params):
55 GatewayRequest.__init__(self, service, method, list(params))
60 def getInputFormat(self):
61 return self.getFormat()
63 def handleResponse(self, response):
65 obj = osrfJSONToObject(s)
66 if obj['status'] != 200:
67 sys.stderr.write('JSON gateway returned status %d:\n%s\n' % (obj['status'], s))
70 # the gateway wraps responses in an array to handle streaming data
71 # if there is only one item in the array, it (probably) wasn't a streaming request
73 if len(p) > 1: return p
76 def encodeParam(self, param):
77 return osrfObjectToJSON(param)
79 class XMLGatewayRequest(GatewayRequest):
81 def __init__(self, service, method, *params):
82 GatewayRequest.__init__(self, service, method, list(params))
87 def getInputFormat(self):
88 return self.getFormat()
90 def handleResponse(self, response):
91 handler = XMLGatewayParser()
92 parser = make_parser()
93 parser.setContentHandler(handler)
94 parser.parse(response)
95 return handler.getResult()
97 def encodeParam(self, param):
98 return osrfObjectToXML(param);
100 class XMLGatewayParser(handler.ContentHandler):
106 self.posStack = [] # for tracking array-based hinted object indices
108 # true if we are parsing an element that may have character data
109 self.charsPending = 0
114 def __getAttr(self, attrs, name):
115 for (k, v) in attrs.items():
120 def startElement(self, name, attrs):
122 if self.charsPending:
123 # we just read a 'string' or 'number' element that resulted
124 # in no text data. Appaned a None object
125 self.appendChild(None)
128 self.appendChild(None)
131 if name == 'string' or name == 'number':
132 self.charsPending = True
135 if name == 'element': # this is an object item wrapper
136 self.keyStack.append(self.__getAttr(attrs, 'key'))
139 hint = self.__getAttr(attrs, 'class_hint')
141 obj = osrfNewObjectFromHint(hint)
142 self.appendChild(obj)
143 self.objStack.append(obj)
145 self.posStack.append(0)
150 self.appendChild(obj)
151 self.objStack.append(obj)
156 self.appendChild(obj)
157 self.objStack.append(obj)
160 if name == 'boolean':
161 self.appendChild((self.__getAttr(attrs, 'value') == 'true'))
165 def appendChild(self, child):
167 if self.result == None:
170 if not self.objStack: return;
172 parent = self.objStack[len(self.objStack)-1]
174 if isinstance(parent, list):
177 if isinstance(parent, dict):
178 parent[self.keyStack.pop()] = child
180 if isinstance(parent, osrfNetworkObject):
182 if parent.getRegistry().wireProtocol == 'array':
183 keys = parent.getRegistry().keys
184 i = self.posStack.pop()
187 self.posStack.append(i+1)
189 key = self.keyStack.pop()
191 parent.setField(key, child)
193 def endElement(self, name):
194 if name == 'array' or name == 'object':
197 def characters(self, chars):
198 self.charsPending = False
199 self.appendChild(urllib.unquote_plus(chars))