Which python soap client supports spyne binary types?
<p>I want to call a web service method that has a spyne binary type as argument.
But I'm not able to find any python soap client supporting it.</p>

<p>To debug my problem, I made a simple web service method that should print a file:</p>

<pre><code>

    #     @srpc(Attachment, _returns=Unicode)
        @srpc(ByteArray, _returns=Unicode)
    #     @srpc(File, _returns=Unicode)
    #     @srpc(Unicode, _returns=Unicode)
        def print_file(file_content):
            logger.info(u"print file:\n{}\ntype:{}".format(file_content, file_content.__class__))

            return u''

</code></pre>

<p>As you can see, I tried with 3 spyne binary types.
For debug, I also tried with Unicode, and passing the file content in base64, and in this case there is no problem. 
Thus the web service is operational.</p>

<p>The server side is a Django application and a spyne application.
My problem is on client side.
With suds, the obtained error is very obscur, and no solution exists according forums.</p>

<p>I tried all SOAP clients described on  <a href="https://wiki.python.org/moin/WebServices#SOAP" rel="nofollow noreferrer">https://wiki.python.org/moin/WebServices#SOAP</a>, with python 2.7 and 3.3.
They all fail when building the request, when serializing the spyne binary object.</p>

<p>My last try is with zeep.
I instantiate the zeep client with wsdl local url.
Sorry, wsdl is not public.</p>

<p>I call this method with an empty ByteArray:
<code></p>

<pre><code>param = ByteArray()
client.service.print_file(param)
</code></pre>

<p></code></p>

<p>The catched exception is:</p>

<pre><code>

        File "/usr/lib/python2.7/site-packages/zeep/client.py", line 41, in __call__
            self._op_name, args, kwargs)
        File "/usr/lib/python2.7/site-packages/zeep/wsdl/bindings/soap.py", line 107, in send
            options=options)
        File "/usr/lib/python2.7/site-packages/zeep/wsdl/bindings/soap.py", line 65, in _create
            serialized = operation_obj.create(*args, **kwargs)
        File "/usr/lib/python2.7/site-packages/zeep/wsdl/definitions.py", line 165, in create
            return self.input.serialize(*args, **kwargs)
        File "/usr/lib/python2.7/site-packages/zeep/wsdl/messages/soap.py", line 48, in serialize
            self.body.render(body, body_value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 333, in render
            self._render_value_item(parent, value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 354, in _render_value_item
            return self.type.render(node, value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/types.py", line 356, in render
            element.render(parent, element_value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/indicators.py", line 189, in render
            element.render(parent, element_value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 333, in render
            self._render_value_item(parent, value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 354, in _render_value_item
            return self.type.render(node, value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/types.py", line 180, in render
            parent.text = self.xmlvalue(value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/builtins.py", line 83, in _wrapper
            return func(self, value)
        File "/usr/lib/python2.7/site-packages/zeep/xsd/builtins.py", line 357, in xmlvalue
            return base64.b64encode(value)
        File "/usr/lib64/python2.7/base64.py", line 53, in b64encode
            encoded = binascii.b2a_base64(s)[:-1]
    TypeError: must be convertible to a buffer, not ModelBaseMeta

</code></pre>

<p><br></p>

<p>Does anyone know if there is a solution with zeep ?<br>
Perhaps with a dedicated zeep plugin ?</p>

<p>Or is there another solution ?<br>
Perhaps in C/C++, compiled as a python package ?</p>

<p>Eric</p>

<p>============================================================ <br>
==  Solution</p>

<p>As I lost a lot of time on this problem, here is the solution for me.</p>

<p>Finally I needed also the filename, not only file data.
The type spyne.model.binary.File would have been perfect, but it is not serialisable into SOAP format.</p>

<p>Thank to discussion with Burak, the final solution is to create a custom ComplexType like:</p>

<pre><code>

class File(ComplexModel):
    filename = Unicode
    data = ByteArray

</code></pre>

<p>On client side with suds, replace the ByteArray field directly with the data encoded in base64:</p>

<pre><code>

    f = File()
    data = open({FILENAME}, "rb").read()
    f.data = base64.b64encode(data)

</code></pre>

<p>On server side, f.data will directly contain the data decoded.</p>