1.1 --- a/libxml2dom/xmlrpc.py Sat Oct 06 20:46:13 2007 +0000
1.2 +++ b/libxml2dom/xmlrpc.py Sat Oct 06 23:48:45 2007 +0000
1.3 @@ -32,7 +32,7 @@
1.4 from libxml2dom.macrolib import *
1.5 from libxml2dom.macrolib import \
1.6 createDocument as Node_createDocument
1.7 -from libxml2dom.rpc import ParameterName, ParameterValue
1.8 +import datetime
1.9
1.10 class XMLRPCImplementation(libxml2dom.Implementation):
1.11
1.12 @@ -169,120 +169,8 @@
1.13 self.appendChild(methodName)
1.14 self.methodNameElement.value = name
1.15
1.16 - def _parameters(self):
1.17 - return self.xpath("./params/param")
1.18 -
1.19 def _parameterValues(self):
1.20 - values = self.xpath("./params/param/value")
1.21 - if values:
1.22 - items = []
1.23 - for value in values:
1.24 - items.append(self._get_value(value))
1.25 - return items
1.26 - else:
1.27 - return []
1.28 -
1.29 - def _setParameterValues(self, parameters):
1.30 - param_list = self.parameters
1.31 - params = (self.xpath("./params") or [None])[0]
1.32 -
1.33 - # Remove any previous parameters.
1.34 -
1.35 - if params:
1.36 - if param_list:
1.37 - for param in param_list:
1.38 - params.removeChild(param)
1.39 - else:
1.40 - params = self.createParameters()
1.41 - self.appendChild(params)
1.42 -
1.43 - # Add parameter values.
1.44 -
1.45 - for parameter in parameters:
1.46 - param = self.ownerDocument.createElement("param")
1.47 - params.appendChild(param)
1.48 - value = self.ownerDocument.createElement("value")
1.49 - param.appendChild(value)
1.50 - self._add_value(value, parameter)
1.51 -
1.52 - # Internal methods.
1.53 -
1.54 - def _add_value(self, value, parameter):
1.55 -
1.56 - "Add to the 'value' element the given 'parameter'."
1.57 -
1.58 - if parameter.name.ns == "struct":
1.59 - if isinstance(parameter.value, dict):
1.60 - items = parameter.value.items()
1.61 - else:
1.62 - items = parameter.value
1.63 -
1.64 - # Create a struct element and add the members.
1.65 -
1.66 - struct = self.ownerDocument.createElement("struct")
1.67 - value.appendChild(struct)
1.68 -
1.69 - for item in items:
1.70 - member = struct.createMember()
1.71 - struct.appendChild(member)
1.72 -
1.73 - # Peek into the item to set up the name.
1.74 -
1.75 - member.memberName = item.name
1.76 -
1.77 - # Add the item inside a new value element.
1.78 -
1.79 - memberValue = member.createValue()
1.80 - member.appendChild(memberValue)
1.81 - self._add_value(memberValue, item)
1.82 -
1.83 - elif parameter.name.ns == "array":
1.84 -
1.85 - # Create an array element and add the members.
1.86 -
1.87 - array = self.ownerDocument.createElement("array")
1.88 - value.appendChild(array)
1.89 - data = array.createData()
1.90 - array.appendChild(data)
1.91 -
1.92 - for item in parameter.value:
1.93 -
1.94 - # Add the item inside a new value element.
1.95 -
1.96 - data_value = data.createValue()
1.97 - data.appendChild(data_value)
1.98 - self._add_value(data_value, item)
1.99 -
1.100 - else:
1.101 - container = self.ownerDocument.createElement(parameter.name.ns)
1.102 - value.appendChild(container)
1.103 - container.value = unicode(parameter.value)
1.104 -
1.105 - def _get_value(self, value, name=None):
1.106 -
1.107 - """
1.108 - Return the parameter name and value from within the given 'value'
1.109 - element, using the optional 'name' as part of the returned name if
1.110 - specified.
1.111 - """
1.112 -
1.113 - if value.type == "struct":
1.114 - items = []
1.115 -
1.116 - # Peek inside member values to get member names.
1.117 -
1.118 - for member in value.container.members:
1.119 - items.append(self._get_value(member.value, member.memberName))
1.120 - return ParameterValue(ParameterName(value.type, name), items)
1.121 -
1.122 - elif value.type == "array":
1.123 - items = []
1.124 - for data_value in value.container.data.values:
1.125 - items.append(self._get_value(data_value))
1.126 - return ParameterValue(ParameterName(value.type, name), items)
1.127 -
1.128 - else:
1.129 - return ParameterValue(ParameterName(value.type, name), value.container.value)
1.130 + return [value.container.contents for value in self.xpath("./params/param/value")]
1.131
1.132 # Node construction methods.
1.133
1.134 @@ -298,8 +186,7 @@
1.135 fault = property(_fault)
1.136 methodNameElement = property(_methodNameElement)
1.137 methodName = property(_methodName, _setMethodName)
1.138 - parameters = property(_parameters)
1.139 - parameterValues = property(_parameterValues, _setParameterValues)
1.140 + parameterValues = property(_parameterValues)
1.141
1.142 class XMLRPCArrayElement(XMLRPCNode):
1.143
1.144 @@ -308,12 +195,36 @@
1.145 def _data(self):
1.146 return (self.xpath("./data") or [None])[0]
1.147
1.148 + def _contents(self):
1.149 + return self
1.150 +
1.151 + # Sequence emulation.
1.152 +
1.153 + def __len__(self):
1.154 + if self.data:
1.155 + return len(self.data)
1.156 + else:
1.157 + return 0
1.158 +
1.159 + def __getitem__(self, i):
1.160 + if self.data:
1.161 + return self.data[i]
1.162 + else:
1.163 + raise IndexError, i
1.164 +
1.165 + def __eq__(self, other):
1.166 + for i, j in map(None, self, other):
1.167 + if i != j:
1.168 + return False
1.169 + return True
1.170 +
1.171 # Node construction methods.
1.172
1.173 def createData(self):
1.174 return self.ownerDocument.createElement("data")
1.175
1.176 data = property(_data)
1.177 + contents = property(_contents)
1.178
1.179 class XMLRPCStructElement(XMLRPCNode):
1.180
1.181 @@ -322,12 +233,30 @@
1.182 def _members(self):
1.183 return self.xpath("./member")
1.184
1.185 + def _contents(self):
1.186 + return self
1.187 +
1.188 + # Sequence emulation.
1.189 +
1.190 + def __len__(self):
1.191 + return len(self.members)
1.192 +
1.193 + def __getitem__(self, i):
1.194 + return self.members[i]
1.195 +
1.196 + def __eq__(self, other):
1.197 + for i, j in map(None, self, other):
1.198 + if i != j:
1.199 + return False
1.200 + return True
1.201 +
1.202 # Node construction methods.
1.203
1.204 def createMember(self):
1.205 return self.ownerDocument.createElement("member")
1.206
1.207 members = property(_members)
1.208 + contents = property(_contents)
1.209
1.210 class XMLRPCDataElement(XMLRPCNode):
1.211
1.212 @@ -336,13 +265,21 @@
1.213 def _values(self):
1.214 return self.xpath("./value")
1.215
1.216 - values = property(_values)
1.217 + # Sequence emulation.
1.218 +
1.219 + def __len__(self):
1.220 + return len(self.values)
1.221 +
1.222 + def __getitem__(self, i):
1.223 + return self.values[i].container.contents
1.224
1.225 # Node construction methods.
1.226
1.227 def createValue(self):
1.228 return self.ownerDocument.createElement("value")
1.229
1.230 + values = property(_values)
1.231 +
1.232 class XMLRPCMemberElement(XMLRPCNode):
1.233
1.234 "An XML-RPC structure member element."
1.235 @@ -365,6 +302,20 @@
1.236 self.appendChild(nameElement)
1.237 self.nameElement.value = name
1.238
1.239 + def _contents(self):
1.240 + return self
1.241 +
1.242 + # Item (name, value) emulation.
1.243 +
1.244 + def __len__(self):
1.245 + return 2
1.246 +
1.247 + def __getitem__(self, i):
1.248 + return (self.memberName, self.value.container.contents)[i]
1.249 +
1.250 + def __eq__(self, other):
1.251 + return self[0] == other[0] and self[1] == other[1]
1.252 +
1.253 # Node construction methods.
1.254
1.255 def createName(self):
1.256 @@ -376,11 +327,14 @@
1.257 value = property(_value)
1.258 nameElement = property(_nameElement)
1.259 memberName = property(_memberName, _setMemberName)
1.260 + contents = property(_contents)
1.261
1.262 class XMLRPCStringElement(XMLRPCNode):
1.263
1.264 "An XML-RPC string element."
1.265
1.266 + typename = "string"
1.267 +
1.268 def _value(self):
1.269 return self.textContent.strip()
1.270
1.271 @@ -390,7 +344,17 @@
1.272 text = self.ownerDocument.createTextNode(value)
1.273 self.appendChild(text)
1.274
1.275 + def _contents(self):
1.276 + return convert(self.typename, self.value)
1.277 +
1.278 + def __eq__(self, other):
1.279 + if hasattr(other, "contents"):
1.280 + return self.contents == other.contents
1.281 + else:
1.282 + return self.contents == other
1.283 +
1.284 value = property(_value, _setValue)
1.285 + contents = property(_contents)
1.286
1.287 class XMLRPCNameElement(XMLRPCStringElement):
1.288
1.289 @@ -425,31 +389,31 @@
1.290
1.291 "An XML-RPC integer element."
1.292
1.293 - pass
1.294 + typename = "int"
1.295
1.296 class XMLRPCBooleanElement(XMLRPCStringElement):
1.297
1.298 "An XML-RPC boolean element."
1.299
1.300 - pass
1.301 + typename = "boolean"
1.302
1.303 class XMLRPCDoubleElement(XMLRPCStringElement):
1.304
1.305 "An XML-RPC double floating point number element."
1.306
1.307 - pass
1.308 + typename = "double"
1.309
1.310 class XMLRPCDateTimeElement(XMLRPCStringElement):
1.311
1.312 "An XML-RPC date/time element."
1.313
1.314 - pass
1.315 + typename = "datetime"
1.316
1.317 class XMLRPCBase64Element(XMLRPCStringElement):
1.318
1.319 "An XML-RPC integer element."
1.320
1.321 - pass
1.322 + typename = "base64"
1.323
1.324 class XMLRPCFaultElement(XMLRPCNode):
1.325
1.326 @@ -472,6 +436,33 @@
1.327 code = property(_code)
1.328 reason = property(_reason)
1.329
1.330 +# Conversion functions.
1.331 +
1.332 +def convert(typename, value):
1.333 + return default_converters[typename](value)
1.334 +
1.335 +def boolean(s):
1.336 + if s.lower() == "true":
1.337 + return True
1.338 + elif s.lower() == "false":
1.339 + return False
1.340 + else:
1.341 + raise ValueError, "String value %s not convertable to boolean." % repr(s)
1.342 +
1.343 +def iso8601(s):
1.344 + year, month, day, hour, minute, second = map(int, (s[:4], s[4:6], s[6:8], s[9:11], s[12:14], s[15:17]))
1.345 + return datetime.datetime(year, month, day, hour, minute, second)
1.346 +
1.347 +default_converters = {
1.348 + "string" : unicode,
1.349 + "int" : int,
1.350 + "i4" : int,
1.351 + "double" : float,
1.352 + "boolean" : boolean,
1.353 + "dateTime.iso8601" : iso8601,
1.354 + "base64" : str
1.355 + }
1.356 +
1.357 # Utility functions.
1.358
1.359 createDocument = libxml2dom.createDocument