Python: How can I use Twisted as the transport for SUDS?

Posted by jathanism on Stack Overflow See other posts from Stack Overflow or by jathanism
Published on 2010-04-19T22:01:05Z Indexed on 2010/04/19 22:03 UTC
Read the original article Hit count: 299

Filed under:
|
|
|
|

I have a project that is based on Twisted used to communicate with network devices and I am adding support for a new vendor (Citrix NetScaler) whose API is SOAP. Unfortunately the support for SOAP in Twisted still relies on SOAPpy, which is badly out of date. In fact as of this question (I just checked), twisted.web.soap itself hasn't even been updated in 21 months!

I would like to ask if anyone has any experience they would be willing to share with utilizing Twisted's superb asynchronous transport functionality with SUDS. It seems like plugging in a custom Twisted transport would be a natural fit in SUDS' Client.options.transport, I'm just having a hard time wrapping my head around it.

I did come up with a way to call the SOAP method with SUDS asynchronously by utilizing twisted.internet.threads.deferToThread(), but this feels like a hack to me.

Here is an example of what I've done, to give you an idea:

# netscaler is a module I wrote using suds to interface with NetScaler SOAP
# Source: http://bitbucket.org/jathanism/netscaler-api/src
import netscaler
import os
import sys
from twisted.internet import reactor, defer, threads

# netscaler.API is the class that sets up the suds.client.Client object
host = 'netscaler.local'
username = password = 'nsroot'
wsdl_url = 'file://' + os.path.join(os.getcwd(), 'NSUserAdmin.wsdl')
api = netscaler.API(host, username=username, password=password, wsdl_url=wsdl_url)

results = []
errors = []

def handleResult(result):
    print '\tgot result: %s' % (result,)
    results.append(result)

def handleError(err):
    sys.stderr.write('\tgot failure: %s' % (err,))
    errors.append(err)

# this converts the api.login() call to a Twisted thread.
# api.login() should return True and is is equivalent to:
# api.service.login(username=self.username, password=self.password)
deferred = threads.deferToThread(api.login)
deferred.addCallbacks(handleResult, handleError)

reactor.run()

This works as expected and defers return of the api.login() call until it is complete, instead of blocking. But as I said, it doesn't feel right.

Thanks in advance for any help, guidance, feedback, criticism, insults, or total solutions.

© Stack Overflow or respective owner

Related posts about python

Related posts about twisted