<div>Hello-</div><div><br></div><div>I have a project that is based on Twisted used to</div><div>communicate with network devices and I am adding support for a new</div><div>vendor (Citrix NetScaler) whose API is SOAP.  Unfortunately the</div>
<div>support for SOAP in Twisted still relies on SOAPpy, which is badly out</div><div>of date. In fact as of this email (I just checked), twisted.web.soap</div><div>itself hasn&#39;t even been updated in 21 months!</div><div>
<br></div><div>I would like to ask if anyone has any experience they would be willing</div><div>to share with utilizing Twisted&#39;s superb asynchronous transport</div><div>functionality with SUDS.  It seems like plugging in a custom Twisted</div>
<div>transport would be a natural fit in SUDS&#39; Client.options.transport, I&#39;m just having</div><div>a hard time wrapping my head around it.</div><div><br></div><div>I did come up with a way to call the SOAP method with SUDS</div>
<div>asynchronously by utilizing twisted.internet.threads.deferToThread(),</div><div>but this feels like a hack to me.</div><div><br></div><div>Here is an example of what I&#39;ve done, just to give you an idea:</div><div>
<br></div><div>   # netscaler is a module I wrote using suds to interface with NetScaler SOAP</div><div>   # Source: <a href="http://bitbucket.org/jathanism/netscaler-api/src">http://bitbucket.org/jathanism/netscaler-api/src</a></div>
<div>   import netscaler</div><div>   import os, sys</div><div>   from twisted.internet import reactor, defer, threads</div><div><br></div><div>   # netscaler.API is the class that sets up the suds.client.Client object</div>
<div>   host = &#39;netscaler.local&#39;</div><div>   username = password = &#39;nsroot&#39;</div><div>   wsdl_url = &#39;file://&#39; + os.path.join(os.getcwd(), &#39;NSUserAdmin.wsdl&#39;)</div><div>   api = netscaler.API(host, username=username, password=password,</div>
<div>wsdl_url=wsdl_url)</div><div><br></div><div>   results = []</div><div>   errors = []</div><div><br></div><div>   def handleResult(result):</div><div>       print &#39;\tgot result: %s&#39; % (result,)</div><div>       results.append(result)</div>
<div><br></div><div>   def handleError(err):</div><div>       sys.stderr.write(&#39;\tgot failure: %s&#39; % (err,))</div><div>       errors.append(err)</div><div><br></div><div>   # this converts the api.login() call to a Twisted thread. </div>
<div>   # api.login() is equivalent to:</div><div>   # api.service.login(username=self.username, password=self.password)</div><div>   deferred = threads.deferToThread(api.login)</div><div>   deferred.addCallbacks(handleResult, handleError)</div>
<div><br></div><div>   reactor.run()</div><div><br></div><div>This works as expected and defers return of the api.login() call until</div><div>it is complete, instead of blocking.  But as I said, it doesn&#39;t feel</div>
<div>right.  </div><div><br></div><div>Thanks in advance for any help, guidance, feedback, criticism,</div><div>insults, or total solutions.</div><div><br></div><div>jathan.</div>