Most of the return types now works with soap
This commit is contained in:
@@ -184,7 +184,6 @@ class WSRoot(object):
|
||||
res_content_type = funcdef.contenttype
|
||||
except Exception, e:
|
||||
infos = self._format_exception(sys.exc_info())
|
||||
log.error(str(infos))
|
||||
if isinstance(e, exc.ClientSideError):
|
||||
res.status = 400
|
||||
else:
|
||||
|
||||
40
wsme/soap.py
40
wsme/soap.py
@@ -6,10 +6,16 @@ Parts of the code were taken from the tgwebservices soap implmentation.
|
||||
import pkg_resources
|
||||
import datetime
|
||||
import decimal
|
||||
import base64
|
||||
|
||||
from simplegeneric import generic
|
||||
|
||||
from xml.etree import ElementTree as et
|
||||
try:
|
||||
from xml.etree import cElementTree as et
|
||||
except ImportError:
|
||||
import cElementTree as et
|
||||
|
||||
from genshi.builder import tag, Element, Namespace
|
||||
from genshi.template import MarkupTemplate
|
||||
from wsme.controller import register_protocol, pexpose
|
||||
import wsme.types
|
||||
@@ -31,12 +37,16 @@ type_registry = {
|
||||
|
||||
|
||||
def make_soap_element(datatype, tag, value):
|
||||
el = et.Element(tag)
|
||||
el = Element(tag)
|
||||
if value is None:
|
||||
el.set('xsi:nil', 'true')
|
||||
el(**{'xsi:nil': 'true'})
|
||||
elif wsme.types.iscomplex(datatype):
|
||||
el(**{'xsi:type': datatype.__name__})
|
||||
for name, attrdef in wsme.types.list_attributes(datatype):
|
||||
el.append(
|
||||
tosoap(attrdef.datatype, name, getattr(value, name)))
|
||||
else:
|
||||
el.set('xsi:type', type_registry.get(datatype))
|
||||
el.text = str(value)
|
||||
el(value, **{'xsi:type': type_registry.get(datatype)})
|
||||
return el
|
||||
|
||||
|
||||
@@ -46,6 +56,17 @@ def tosoap(datatype, tag, value):
|
||||
response output"""
|
||||
return make_soap_element(datatype, tag, value)
|
||||
|
||||
@tosoap.when_object(datetime.datetime)
|
||||
def datetime_tosoap(datatype, tag, value):
|
||||
return make_soap_element(datatype, tag,
|
||||
value is not None and value.isoformat() or None)
|
||||
|
||||
@tosoap.when_object(wsme.types.binary)
|
||||
def binary_tosoap(datatype, tag, value):
|
||||
return make_soap_element(datatype, tag,
|
||||
value is not None and base64.encodestring(value)
|
||||
or None)
|
||||
|
||||
@tosoap.when_object(None)
|
||||
def None_tosoap(datatype, tag, value):
|
||||
return make_soap_element(datatype, tag, None)
|
||||
@@ -94,8 +115,9 @@ class SoapProtocol(object):
|
||||
body = el.find('{%(soapenv)s}Body' % self.ns)
|
||||
# Extract the service name from the tns
|
||||
fname = list(body)[0].tag
|
||||
if fname.startswith('{%s}' % self.tns):
|
||||
fname = fname[len(self.tns)+2:]
|
||||
if fname.startswith('{%s}' % self.typenamespace):
|
||||
fname = fname[len(self.typenamespace)+2:]
|
||||
print fname
|
||||
return self.get_name_mapping()[fname]
|
||||
return None
|
||||
|
||||
@@ -103,9 +125,9 @@ class SoapProtocol(object):
|
||||
return {}
|
||||
|
||||
def soap_response(self, funcdef, result):
|
||||
r = et.Element('{' + self.tns + '}' + self.soap_fname(funcdef) + 'Response')
|
||||
r = Element(self.soap_fname(funcdef) + 'Response')
|
||||
r.append(tosoap(funcdef.return_type, 'result', result))
|
||||
return et.tostring(r)
|
||||
return r
|
||||
|
||||
def encode_result(self, funcdef, result):
|
||||
envelope = self.render_template('soap',
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
xmlns:py="http://genshi.edgewall.org/"
|
||||
py:attrs="{'xmlns' : typenamespace}">
|
||||
<soapenv:Body>
|
||||
${Markup(soap_response(funcdef, result))}
|
||||
${soap_response(funcdef, result)}
|
||||
</soapenv:Body>
|
||||
</soapenv:Envelope>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import decimal
|
||||
import datetime
|
||||
import base64
|
||||
|
||||
import wsme.tests.protocol
|
||||
|
||||
@@ -9,11 +10,15 @@ except:
|
||||
import cElementTree as et
|
||||
|
||||
import wsme.soap
|
||||
import wsme.utils
|
||||
|
||||
tns = "http://foo.bar.baz/soap/"
|
||||
typenamespace = "http://foo.bar.baz/types/"
|
||||
|
||||
soapenv_ns = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi_ns = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
body_qn = '{%s}Body' % soapenv_ns
|
||||
type_qn = '{%s}type' % xsi_ns
|
||||
|
||||
def build_soap_message(method, params=""):
|
||||
message = """<?xml version="1.0"?>
|
||||
@@ -22,14 +27,16 @@ xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
|
||||
<soap:Body xmlns="%(tns)s">
|
||||
<soap:Body xmlns="%(typenamespace)s">
|
||||
<%(method)s>
|
||||
%(params)s
|
||||
</%(method)s>
|
||||
</soap:Body>
|
||||
|
||||
</soap:Envelope>
|
||||
""" % dict(method=method, params=params, tns=tns)
|
||||
""" % dict(method=method,
|
||||
params=params,
|
||||
typenamespace=typenamespace)
|
||||
return message
|
||||
|
||||
|
||||
@@ -56,20 +63,42 @@ def loadxml(el):
|
||||
else:
|
||||
return el.text
|
||||
|
||||
def read_bool(value):
|
||||
return value == 'true'
|
||||
|
||||
soap_types = {
|
||||
'xsi:int': int
|
||||
'xsd:string': unicode,
|
||||
'xsd:int': int,
|
||||
'xsd:long': long,
|
||||
'xsd:float': float,
|
||||
'xsd:decimal': decimal.Decimal,
|
||||
'xsd:boolean': read_bool,
|
||||
'xsd:date': wsme.utils.parse_isodate,
|
||||
'xsd:time': wsme.utils.parse_isotime,
|
||||
'xsd:dateTime': wsme.utils.parse_isodatetime,
|
||||
'xsd:base64Binary': base64.decodestring,
|
||||
}
|
||||
|
||||
def fromsoap(el):
|
||||
t = el.get('type')
|
||||
t = el.get(type_qn)
|
||||
print t
|
||||
if t in soap_types:
|
||||
print t, el.text
|
||||
return soap_types[t](el.text)
|
||||
return None
|
||||
else:
|
||||
d = {}
|
||||
for child in el:
|
||||
name = child.tag
|
||||
assert name.startswith('{%s}' % typenamespace)
|
||||
name = name[len(typenamespace)+2:]
|
||||
d[name] = fromsoap(child)
|
||||
print d
|
||||
return d
|
||||
|
||||
|
||||
class TestSOAP(wsme.tests.protocol.ProtocolTestCase):
|
||||
protocol = wsme.soap.SoapProtocol(tns=tns)
|
||||
protocol = wsme.soap.SoapProtocol(
|
||||
tns=tns, typenamespace=typenamespace)
|
||||
|
||||
def test_simple_call(self):
|
||||
message = build_soap_message('Touch')
|
||||
@@ -98,8 +127,9 @@ class TestSOAP(wsme.tests.protocol.ProtocolTestCase):
|
||||
print body
|
||||
|
||||
if res.status_int == 200:
|
||||
r = body.find('{%s}%sResponse' % (tns, methodname))
|
||||
result = r.find('{%s}result' % tns)
|
||||
r = body.find('{%s}%sResponse' % (typenamespace, methodname))
|
||||
result = r.find('{%s}result' % typenamespace)
|
||||
print result
|
||||
return fromsoap(result)
|
||||
elif res.status_int == 400:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user