Search code examples
pythonspyne

Using Python Spyne (RPC) is there a way to return a native python list instead of the fancy Array or Iterable?


Both the Iterable and Array types seem to have a native list hidden away in them, but I find myself always doing things like:

myList = service.fetchRemoteList()[0][1] 

Where fetchRemoteList() _returns=Iterable(String)

I don't want to have to put [0][1] at the end of all my list function calls.


Solution

  • Spyne uses wrapped arrays by default, because that's what everybody else in the XML world does.

    Wrapped array:

    <users>
        <User>
            <id>1</id>
            <name>Batman</name>
        </User>
        <User>
            <id>2</id>
            <name>Robin</name>
        </User>
    </users>
    

    Bare array:

    <users>
        <id>1</id>
        <name>Batman</name>
    </users>
    <users>
        <id>2</id>
        <name>Robin</name>
    </users>
    

    You probably can see why everybody likes wrapped arrays better now. It's a matter of convention, but surely a helpful one. Plus, it's not possible to do polymorphism with non-wrapped arrays.

    Spyne also uses wrapped functions by default, because it's not possible to have multiple arguments / return values in bare mode.

    Now the answers:

    • Here's a wrapped array:

      Array(Unicode)
      

      Here's the equivalent bare array:

      Unicode(max_occurs='unbounded')
      

      In 2.12, you can also pass wrapped=False to Array to get bare arrays. Eg.:

      Array(Unicode, wrapped=False)
      
    • As you discovered, you can get bare functions passing _body_style='bare' to @rpc.

    Some SOAP clients discover what kind of function/array it is via simple heuristics and save you the trouble of using magic indexes. Apparently suds isn't one of them.