1.1 --- a/libxml2dom/conversions.py Mon Oct 01 23:27:18 2007 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,49 +0,0 @@
1.4 -#!/usr/bin/env python
1.5 -
1.6 -"""
1.7 -Conversion functions and data used by XML-RPC and SOAP.
1.8 -
1.9 -Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk>
1.10 -
1.11 -This program is free software; you can redistribute it and/or modify it under
1.12 -the terms of the GNU Lesser General Public License as published by the Free
1.13 -Software Foundation; either version 3 of the License, or (at your option) any
1.14 -later version.
1.15 -
1.16 -This program is distributed in the hope that it will be useful, but WITHOUT
1.17 -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1.19 -details.
1.20 -
1.21 -You should have received a copy of the GNU Lesser General Public License along
1.22 -with this program. If not, see <http://www.gnu.org/licenses/>.
1.23 -"""
1.24 -
1.25 -converters = {
1.26 - "string" : unicode,
1.27 - "int" : int,
1.28 - "i4" : int,
1.29 - "double" : float,
1.30 - "boolean" : boolean, # see the module globals
1.31 - "dateTime.iso8601" : iso8601, # see the module globals
1.32 - "base64" : str
1.33 - }
1.34 -
1.35 -def from_string(typename, value):
1.36 - return converters.get(typename, str)(value)
1.37 -
1.38 -# Utility functions.
1.39 -
1.40 -def boolean(s):
1.41 - if s.lower() == "true":
1.42 - return True
1.43 - elif s.lower() == "false":
1.44 - return False
1.45 - else:
1.46 - raise ValueError, "String value %s not convertable to boolean." % repr(s)
1.47 -
1.48 -def iso8601(s):
1.49 - # NOTE: To be written.
1.50 - return s
1.51 -
1.52 -# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/libxml2dom/rpc.py Sat Oct 06 19:33:22 2007 +0000
2.3 @@ -0,0 +1,102 @@
2.4 +#!/usr/bin/env python
2.5 +
2.6 +"""
2.7 +Conversion functions and data used by XML-RPC and SOAP.
2.8 +
2.9 +Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk>
2.10 +
2.11 +This program is free software; you can redistribute it and/or modify it under
2.12 +the terms of the GNU Lesser General Public License as published by the Free
2.13 +Software Foundation; either version 3 of the License, or (at your option) any
2.14 +later version.
2.15 +
2.16 +This program is distributed in the hope that it will be useful, but WITHOUT
2.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.18 +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2.19 +details.
2.20 +
2.21 +You should have received a copy of the GNU Lesser General Public License along
2.22 +with this program. If not, see <http://www.gnu.org/licenses/>.
2.23 +"""
2.24 +
2.25 +import datetime
2.26 +
2.27 +# Utility classes.
2.28 +
2.29 +class ParameterName(object):
2.30 +
2.31 + "A method parameter name."
2.32 +
2.33 + def __init__(self, ns, name):
2.34 + self.ns = ns
2.35 + self.name = name
2.36 +
2.37 + def __eq__(self, other):
2.38 + other_ns, other_name = other
2.39 + return self.ns, to_localName(self.name) == other_ns, to_localName(other_name)
2.40 +
2.41 + def __hash__(self):
2.42 + return hash(self.ns + to_localName(self.name))
2.43 +
2.44 + def __repr__(self):
2.45 + return "ParameterName(%s, %s)" % (repr(self.ns), repr(self.name or None))
2.46 +
2.47 + # Sequence emulation.
2.48 +
2.49 + def __len__(self):
2.50 + return 2
2.51 +
2.52 + def __getitem__(self, i):
2.53 + return (self.ns, self.name)[i]
2.54 +
2.55 +def to_localName(name):
2.56 + return (name or "").split(":")[-1] or None
2.57 +
2.58 +def convert(parameters, converters=None):
2.59 +
2.60 + """
2.61 + Convert the 'parameters', returning a list of name, value items where the
2.62 + names are the plain names for each parameter, and the values may be
2.63 + converted from strings to other data types.
2.64 + """
2.65 +
2.66 + conv = default_converters
2.67 + conv.update(converters or {})
2.68 + results = []
2.69 + for parameter_name, parameter_value in parameters:
2.70 + typename, name = parameter_name
2.71 + localName = to_localName(name)
2.72 + if isinstance(parameter_value, list):
2.73 + value = convert(parameter_value, converters)
2.74 + else:
2.75 + functions = conv.get(typename, {})
2.76 + function = functions.get(localName) or functions.get(None, unicode)
2.77 + value = function(parameter_value)
2.78 + results.append((localName, value))
2.79 + return results
2.80 +
2.81 +# Utility functions.
2.82 +
2.83 +def boolean(s):
2.84 + if s.lower() == "true":
2.85 + return True
2.86 + elif s.lower() == "false":
2.87 + return False
2.88 + else:
2.89 + raise ValueError, "String value %s not convertable to boolean." % repr(s)
2.90 +
2.91 +def iso8601(s):
2.92 + # NOTE: To be written.
2.93 + return s
2.94 +
2.95 +default_converters = {
2.96 + "string" : {None : unicode},
2.97 + "int" : {None : int},
2.98 + "i4" : {None : int},
2.99 + "double" : {None : float},
2.100 + "boolean" : {None : boolean},
2.101 + "dateTime.iso8601" : {None : iso8601},
2.102 + "base64" : {None : str}
2.103 + }
2.104 +
2.105 +# vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/libxml2dom/soap.py Mon Oct 01 23:27:18 2007 +0000
3.2 +++ b/libxml2dom/soap.py Sat Oct 06 19:33:22 2007 +0000
3.3 @@ -32,6 +32,7 @@
3.4 from libxml2dom.macrolib import *
3.5 from libxml2dom.macrolib import \
3.6 createDocument as Node_createDocument
3.7 +from libxml2dom.rpc import ParameterName
3.8
3.9 # SOAP-related namespaces.
3.10
3.11 @@ -224,13 +225,13 @@
3.12 def _parameters(self):
3.13 return self.xpath("*")
3.14
3.15 - def _parameterValues(self):
3.16 + def _rawParameterValues(self):
3.17 values = []
3.18 for parameter in self.parameters:
3.19 values.append(self._get_value(parameter))
3.20 return values
3.21
3.22 - def _setParameterValues(self, parameters):
3.23 + def _setRawParameterValues(self, parameters):
3.24 for node in self.parameters:
3.25 self.removeChild(node)
3.26
3.27 @@ -239,38 +240,48 @@
3.28 for parameter in parameters:
3.29 self._add_value(self, parameter)
3.30
3.31 + def _parameterValues(self):
3.32 + return libxml2dom.rpc.convert(self.rawParameterValues, getattr(self.ownerDocument, "converters", None))
3.33 +
3.34 # Internal methods.
3.35
3.36 def _add_value(self, value, parameter):
3.37 - (ns, name), parameter = parameter
3.38 - container = self.ownerDocument.createElementNS(ns, name)
3.39 +
3.40 + "Add to the 'value' element the given 'parameter'."
3.41 +
3.42 + parameter_name, parameter_value = parameter
3.43 + container = self.ownerDocument.createElementNS(*parameter_name)
3.44 value.appendChild(container)
3.45 - if isinstance(parameter, (list, dict)):
3.46 - if isinstance(parameter, dict):
3.47 - items = parameter.items()
3.48 + if isinstance(parameter_value, (list, dict)):
3.49 + if isinstance(parameter_value, dict):
3.50 + items = parameter_value.items()
3.51 else:
3.52 - items = parameter
3.53 + items = parameter_value
3.54 for item in items:
3.55 self._add_value(container, item)
3.56 else:
3.57 - text = self.ownerDocument.createTextNode(unicode(parameter))
3.58 + text = self.ownerDocument.createTextNode(unicode(parameter_value))
3.59 container.appendChild(text)
3.60
3.61 def _get_value(self, parameter):
3.62 +
3.63 + "Return the parameter name and value from within the given 'parameter'."
3.64 +
3.65 elements = parameter.xpath("*")
3.66 if elements:
3.67 items = []
3.68 for element in elements:
3.69 items.append(self._get_value(element))
3.70 - return (parameter.namespaceURI, parameter.name), items
3.71 + return ParameterName(parameter.namespaceURI, parameter.name), items
3.72 else:
3.73 - return (parameter.namespaceURI, parameter.name), parameter.textContent.strip()
3.74 + return ParameterName(parameter.namespaceURI, parameter.name), parameter.textContent.strip()
3.75
3.76 methodName = property(_methodName)
3.77 resultParameter = property(_resultParameter)
3.78 resultParameterValue = property(_resultParameterValue)
3.79 parameters = property(_parameters)
3.80 - parameterValues = property(_parameterValues, _setParameterValues)
3.81 + rawParameterValues = property(_rawParameterValues, _setRawParameterValues)
3.82 + parameterValues = property(_parameterValues)
3.83
3.84 class SOAPFaultElement(SOAPNode):
3.85
4.1 --- a/libxml2dom/xmlrpc.py Mon Oct 01 23:27:18 2007 +0000
4.2 +++ b/libxml2dom/xmlrpc.py Sat Oct 06 19:33:22 2007 +0000
4.3 @@ -32,7 +32,7 @@
4.4 from libxml2dom.macrolib import *
4.5 from libxml2dom.macrolib import \
4.6 createDocument as Node_createDocument
4.7 -import datetime
4.8 +from libxml2dom.rpc import ParameterName
4.9
4.10 class XMLRPCImplementation(libxml2dom.Implementation):
4.11
4.12 @@ -82,6 +82,10 @@
4.13 return XMLRPCValueElement(_node, self, context_node.ownerDocument)
4.14 elif Node_localName(_node) == "name":
4.15 return XMLRPCNameElement(_node, self, context_node.ownerDocument)
4.16 + elif Node_localName(_node) == "array":
4.17 + return XMLRPCArrayElement(_node, self, context_node.ownerDocument)
4.18 + elif Node_localName(_node) == "data":
4.19 + return XMLRPCDataElement(_node, self, context_node.ownerDocument)
4.20
4.21 # Otherwise, make generic XML-RPC elements.
4.22
4.23 @@ -168,7 +172,7 @@
4.24 def _parameters(self):
4.25 return self.xpath("./params/param")
4.26
4.27 - def _parameterValues(self):
4.28 + def _rawParameterValues(self):
4.29 values = self.xpath("./params/param/value")
4.30 if values:
4.31 items = []
4.32 @@ -178,7 +182,7 @@
4.33 else:
4.34 return []
4.35
4.36 - def _setParameterValues(self, parameters):
4.37 + def _setRawParameterValues(self, parameters):
4.38 param_list = self.parameters
4.39 params = (self.xpath("./params") or [None])[0]
4.40
4.41 @@ -201,37 +205,90 @@
4.42 param.appendChild(value)
4.43 self._add_value(value, parameter)
4.44
4.45 + def _parameterValues(self):
4.46 + return libxml2dom.rpc.convert(self.rawParameterValues)
4.47 +
4.48 # Internal methods.
4.49
4.50 def _add_value(self, value, parameter):
4.51 - typename, parameter = parameter
4.52 +
4.53 + "Add to the 'value' element the given 'parameter'."
4.54 +
4.55 + (typename, parameter_name), parameter_value = parameter
4.56 +
4.57 if typename == "struct":
4.58 - if isinstance(parameter, dict):
4.59 - items = parameter.items()
4.60 + if isinstance(parameter_value, dict):
4.61 + items = parameter_value.items()
4.62 else:
4.63 - items = parameter
4.64 + items = parameter_value
4.65 +
4.66 + # Create a struct element and add the members.
4.67 +
4.68 struct = self.ownerDocument.createElement("struct")
4.69 - for item_name, item_value in items:
4.70 + value.appendChild(struct)
4.71 +
4.72 + for item in items:
4.73 + (item_typename, item_name), item_value = item
4.74 member = struct.createMember()
4.75 struct.appendChild(member)
4.76 +
4.77 + # Peek into the item to set up the name.
4.78 +
4.79 member.memberName = item_name
4.80 +
4.81 + # Add the item inside a new value element.
4.82 +
4.83 memberValue = member.createValue()
4.84 member.appendChild(memberValue)
4.85 - self._add_value(memberValue, item_value)
4.86 - value.appendChild(struct)
4.87 + self._add_value(memberValue, item)
4.88 +
4.89 + elif typename == "array":
4.90 +
4.91 + # Create an array element and add the members.
4.92 +
4.93 + array = self.ownerDocument.createElement("array")
4.94 + value.appendChild(array)
4.95 + data = array.createData()
4.96 + array.appendChild(data)
4.97 +
4.98 + for item in parameter_value:
4.99 +
4.100 + # Add the item inside a new value element.
4.101 +
4.102 + data_value = data.createValue()
4.103 + data.appendChild(data_value)
4.104 + self._add_value(data_value, item)
4.105 +
4.106 else:
4.107 container = self.ownerDocument.createElement(typename)
4.108 value.appendChild(container)
4.109 - container.value = unicode(parameter)
4.110 + container.value = unicode(parameter_value)
4.111 +
4.112 + def _get_value(self, value, name=None):
4.113
4.114 - def _get_value(self, value):
4.115 + """
4.116 + Return the parameter name and value from within the given 'value'
4.117 + element, using the optional 'name' as part of the returned name if
4.118 + specified.
4.119 + """
4.120 +
4.121 if value.type == "struct":
4.122 items = []
4.123 +
4.124 + # Peek inside member values to get member names.
4.125 +
4.126 for member in value.container.members:
4.127 - items.append((member.memberName, self._get_value(member.value)))
4.128 - return (value.type, items)
4.129 + items.append(self._get_value(member.value, member.memberName))
4.130 + return (ParameterName(value.type, name), items)
4.131 +
4.132 + elif value.type == "array":
4.133 + items = []
4.134 + for data_value in value.container.data.values:
4.135 + items.append(self._get_value(data_value))
4.136 + return (ParameterName(value.type, name), items)
4.137 +
4.138 else:
4.139 - return (value.type, value.container.value)
4.140 + return (ParameterName(value.type, name), value.container.value)
4.141
4.142 # Node construction methods.
4.143
4.144 @@ -248,7 +305,22 @@
4.145 methodNameElement = property(_methodNameElement)
4.146 methodName = property(_methodName, _setMethodName)
4.147 parameters = property(_parameters)
4.148 - parameterValues = property(_parameterValues, _setParameterValues)
4.149 + rawParameterValues = property(_rawParameterValues, _setRawParameterValues)
4.150 + parameterValues = property(_parameterValues)
4.151 +
4.152 +class XMLRPCArrayElement(XMLRPCNode):
4.153 +
4.154 + "An XML-RPC array element."
4.155 +
4.156 + def _data(self):
4.157 + return (self.xpath("./data") or [None])[0]
4.158 +
4.159 + # Node construction methods.
4.160 +
4.161 + def createData(self):
4.162 + return self.ownerDocument.createElement("data")
4.163 +
4.164 + data = property(_data)
4.165
4.166 class XMLRPCStructElement(XMLRPCNode):
4.167
4.168 @@ -264,10 +336,27 @@
4.169
4.170 members = property(_members)
4.171
4.172 +class XMLRPCDataElement(XMLRPCNode):
4.173 +
4.174 + "An XML-RPC array data element."
4.175 +
4.176 + def _values(self):
4.177 + return self.xpath("./value")
4.178 +
4.179 + values = property(_values)
4.180 +
4.181 + # Node construction methods.
4.182 +
4.183 + def createValue(self):
4.184 + return self.ownerDocument.createElement("value")
4.185 +
4.186 class XMLRPCMemberElement(XMLRPCNode):
4.187
4.188 "An XML-RPC structure member element."
4.189
4.190 + def _value(self):
4.191 + return (self.xpath("./value") or [None])[0]
4.192 +
4.193 def _nameElement(self):
4.194 return (self.xpath("./name") or [None])[0]
4.195
4.196 @@ -283,9 +372,6 @@
4.197 self.appendChild(nameElement)
4.198 self.nameElement.value = name
4.199
4.200 - def _value(self):
4.201 - return (self.xpath("./value") or [None])[0]
4.202 -
4.203 # Node construction methods.
4.204
4.205 def createName(self):
4.206 @@ -294,9 +380,9 @@
4.207 def createValue(self):
4.208 return self.ownerDocument.createElement("value")
4.209
4.210 + value = property(_value)
4.211 nameElement = property(_nameElement)
4.212 memberName = property(_memberName, _setMemberName)
4.213 - value = property(_value)
4.214
4.215 class XMLRPCStringElement(XMLRPCNode):
4.216