From ed87a5b30e80d9d5d6ccf7c48b598d66ed9eaa3a Mon Sep 17 00:00:00 2001 From: jortel Date: Tue, 24 Nov 2009 17:33:58 +0000 Subject: [PATCH] Provides the unmarshaller part of the 'enhanced soap encoded array support'. Flattens soap encoded arrays returned by rpc/encoded servers into python lists. ** IMPORTANT: This changes (improves) the form of returned soap encoded arrays. They are now flattened. Old, person.pets=(Pets)pets[]=[pet,], New person.pets=[pet,]. git-svn-id: http://svn.fedorahosted.org/svn/suds/trunk@607 0b8c961e-115e-4cb0-8d11-a7d6dae58e8c --- suds/bindings/rpc.py | 14 ++++++- suds/umx/encoded.py | 92 ++++++++++++++++++++++++++++++++++++++++++++ tests/axis1.py | 5 ++- tests/axis2.py | 14 +++---- tests/public.py | 9 +++-- 5 files changed, 119 insertions(+), 15 deletions(-) create mode 100644 suds/umx/encoded.py diff --git a/suds/bindings/rpc.py b/suds/bindings/rpc.py index 3738632..9acd3e1 100644 --- a/suds/bindings/rpc.py +++ b/suds/bindings/rpc.py @@ -21,6 +21,7 @@ from logging import getLogger from suds import * from suds.mx.encoded import Encoded as MxEncoded +from suds.umx.encoded import Encoded as UmxEncoded from suds.bindings.binding import Binding, envns from suds.sax.element import Element @@ -83,4 +84,15 @@ class Encoded(RPC): """ def marshaller(self): - return MxEncoded(self.schema) \ No newline at end of file + return MxEncoded(self.schema) + + def unmarshaller(self, typed=True): + """ + Get the appropriate XML decoder. + @return: Either the (basic|typed) unmarshaller. + @rtype: L{UmxTyped} + """ + if typed: + return UmxEncoded(self.schema) + else: + return RPC.unmarshaller(self, typed) diff --git a/suds/umx/encoded.py b/suds/umx/encoded.py new file mode 100644 index 0000000..10fd2c4 --- /dev/null +++ b/suds/umx/encoded.py @@ -0,0 +1,92 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the (LGPL) GNU Lesser General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library Lesser General Public License for more details at +# ( http://www.gnu.org/licenses/lgpl.html ). +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# written by: Jeff Ortel ( jortel@redhat.com ) + +""" +Provides soap encoded unmarshaller classes. +""" + +from logging import getLogger +from suds import * +from suds.umx import * +from suds.umx.typed import Typed +from suds.sax import splitPrefix +from suds.xsd.query import TypeQuery + +log = getLogger(__name__) + + +Content.extensions.append('aty') + + +class Encoded(Typed): + """ + A SOAP section (5) encoding unmarshaller. + This marshaller supports rpc/encoded soap styles. + """ + + def start(self, content): + # + # Grab the array type and continue + # + start = Typed.start(self, content) + self.setaty(content) + return start + + def end(self, content): + # + # Squash soap encoded arrays into python lists. This is + # also where we insure that empty arrays are represented + # as empty python lists. + # + aty = content.aty + if aty is not None: + pylist = [] + if len(content.data): + items = content.data[0] + for x in items: + pylist.append(aty.translate(x)) + content.data = pylist + return Typed.end(self, content) + + def postprocess(self, content): + # + # Ensure proper rendering of empty arrays. + # + if content.aty is None: + return Typed.postprocess(self, content) + else: + return content.data + + def setaty(self, content): + """ + Grab the (aty) soap-enc:arrayType and attach it to the + content for proper array processing later in end(). + @param content: The current content being unmarshalled. + @type content: L{Content} + @return: self + @rtype: L{Encoded} + """ + spns = (None, 'http://schemas.xmlsoap.org/soap/encoding/') + aty = content.node.get('arrayType', spns) + if aty is None: + return + aty = aty.split('[')[0] + p,t = splitPrefix(aty) + ns = content.node.resolvePrefix(p) + qref = (t, ns[1]) + query = TypeQuery(qref) + content.aty = query.execute(self.resolver.schema) + return self \ No newline at end of file diff --git a/tests/axis1.py b/tests/axis1.py index d96520e..84c4589 100644 --- a/tests/axis1.py +++ b/tests/axis1.py @@ -37,7 +37,7 @@ setup_logging() -logging.getLogger('suds.client').setLevel(logging.DEBUG) +#logging.getLogger('suds.client').setLevel(logging.DEBUG) def start(url): global errors @@ -48,7 +48,7 @@ def start(url): url = 'http://localhost:8081/axis/services/basic-rpc-encoded?wsdl' start(url) t = HttpAuthenticated(**credentials) - client = Client(url, transport=t) + client = Client(url, transport=t, cache=None) print client # # create a name object using the wsdl @@ -193,6 +193,7 @@ def start(url): print 'getList(%s, %d)' % (s, n) result = client.service.getList(s, n) print '\nreply( %s )\n' % str(result) + assert ( isinstance(result, list) and len(result) == n ) except WebFault, f: errors += 1 print f diff --git a/tests/axis2.py b/tests/axis2.py index aa8e63d..8ed0bdd 100644 --- a/tests/axis2.py +++ b/tests/axis2.py @@ -29,7 +29,7 @@ setup_logging() -logging.getLogger('suds.client').setLevel(logging.DEBUG) +#logging.getLogger('suds.client').setLevel(logging.DEBUG) url = 'http://localhost:8080/axis2/services/BasicService?wsdl' @@ -172,13 +172,11 @@ # # test list returned # -print 'getList(str, 1)' -result = client.service.getList('hello', 1) -print '\nreply( %s )\n' % str(result) - -print 'getList(str, 3)' -result = client.service.getList('hello', 3) -print '\nreply( %s )\n' % str(result) +for n in range(0, 3): + print 'getList(str, %d)' % n + result = client.service.getList('hello', n) + print '\nreply( %s )\n' % str(result) + assert ( isinstance(result, list) and len(result) == n ) print 'addPet()' dog = client.factory.create('ns2:Dog') diff --git a/tests/public.py b/tests/public.py index fb9103b..d40ca87 100644 --- a/tests/public.py +++ b/tests/public.py @@ -59,13 +59,14 @@ def start(url): result = client.service.echoFloat(input) print 'echoFloat() = %s' % result assert result == input - input = [1,2,3,4] # suds 0.3.8+ + result = client.service.echoIntegerArray([]) + print 'echoIntegerArray() = %s' % result + assert result is None + input = [1,2,3,4] result = client.service.echoIntegerArray(input) print 'echoIntegerArray() = %s' % result - # looks like umx package needs an 'encoded' unmarshaller - # that respects arrayType="" and creates a python []. - # assert result == input + assert result == input except WebFault, f: errors += 1 print f