Utilizing Twisted for transport w/ suds
by Jathan McCollum
Hello-
I am new to the list but have been using suds for at least a year now
and I find it to be pretty much the de facto standard Python SOAP
library. 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 email (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 Client.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, just 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, 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
# api.login() 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.
--
Jathan.
--
14 years
Setting Value of Extension of types
by Garth Bushell
Hi,
I'm Fairly new to using SOAP so this may be stupid but..
There is a type in the Vware Vim api[1] defined as an extension of
xsd:string as below.
<complexType name="ManagedObjectReference">
<simpleContent>
<extension base="xsd:string">
<attribute name="type" type="xsd:string"/>
</extension>
</simpleContent>
</complexType>
I believe it is extending the type String and adding an attribute called "type".
Within the Java and C# SOAP wrappers these generate a class with two attributes
"type" from ManagedObjectReference and "value" from xsd:string.
The Suds call "mor=client.factory.create('ns0:ManagedObjectReference')"
generates a
object but it seems to be missing the value attribute.
>>> print mor.__keylist__
['_type']
How do I set the value of the xsd:string of the ManagedObjectReference
within suds?
as I can only set the type not the value of the xs:string I'm extending.
Hope this makes sense.
Cheers
Garth
[1] - http://www.vmware.com/support/developer/vc-sdk/
14 years
local schemaLocation values
by Christopher Hesse
*
In version 0.3.9 of suds, the following in a WSDL file:
<xsd:import namespace="http://example.com/" schemaLocation="file:Basic.xsd"
/>
fails with an error that it couldn't find "/Basic.xsd"
I think the problem is the two lines in sxbasic.py that look like
"if* *'://'* *not* *in* url:"
I replaced this with
*"if* *':'* *not* *in* url:"
and it worked for me, though I don't know enough about XML schemas to know
if that's legit for everyone.
Thanks!
-Chris
14 years
Handling of complex return values
by Martin Aspeli
Hi,
In our project, we're using two different sets of web services,
written by two different organisations. I think both are written in
Java, but that's not necessarily saying much.
In one of the cases, we have a method like getFoo(). Suds has found a
complex type getFooResponse. This has an attribute 'response', of a
complex type fooData (also found by Suds) that is specific to the
method and contains various attributes.
In the other service, we have a method like getBar(). The return value
is being listed as getBarResponse. This has an attribute 'return', of
a complex type barData (also found by Suds) that is specific to the
method and contains various attributes.
Interestingly, when we call the first service, we get back the
getFooResponse complex object, and we have to do
'getFooResponse.response' to get the real fooData object we're
interested in. In the second service, Suds seems to do this unpacking
for us, so the return value is a barData directly, and to my knowledge
we don't use the getBarResponse complex type anywhere.
Why are these two services behaving differently?
Cheers,
Martin
14 years
suds client and soaplib
by John Aherne
I am using the soaplib trivial helloworld.py example.
I can call soaplib from suds using simple types as the first example shows
below.
I pass 2 simple types a name and an integer value. And I get the response
repeated the number of times of the integer value.
But I am having a problem with calling soaplib from suds using the
client.factory_create method.
This you can see in the 2nd example.
Looking at the log output it seems that it is SUDS that has the problem -
but I am no expert on this.
It looks like it is trying to create a structure for a complex type and to
me it seems like it is not doing it correctly.
It could be I'm doing this all wrong. And I should be sticking to avoiding
the client factory for this type of message.
But I thought I would check and see if someone can give me some pointers as
to what I should be doing.
Needless to say I am not that well up in soap messages
Thanks for any info
John Aherne
************************************
1st example
************************************
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
client= Client("http://localhost:7889/wsdl",cache=None)
print client
print client.service.say_hello("punk",5)
E:\soaplib-0.8.1\examples>test_suds.py
Suds ( https://fedorahosted.org/suds/ ) version: 0.3.9 GA build:
R659-20100219
Service ( HelloWorldService ) tns="HelloWorldService.HelloWorldService"
Prefixes (1)
ns0 = "HelloWorldService.HelloWorldService"
Ports (1):
(HelloWorldService)
Methods (1):
say_hello(xs:string name, xs:integer times, )
Types (3):
say_hello
say_helloResponse
stringArray
DEBUG:suds.client:sending to (http://localhost:7889/wsdl)
message:
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:n
s1="HelloWorldService.HelloWorldService" xmlns:xsi="
http://www.w3.org/2001/XMLSc
hema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns1:say_hello>
<name>punk</name>
<times>5</times>
</ns1:say_hello>
</ns0:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': u'"say_hello"', 'Content-Type':
'text
/xml'}
DEBUG:suds.client:http succeeded:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:S
OAP-ENV="http://schemas.xmlsoap.org/soap/envelope/
"><SOAP-ENV:Body><say_helloRes
ponse><say_helloResult type="tns:stringArray"><string
xsi:type="xs:string">Hello
, punk</string><string xsi:type="xs:string">Hello, punk</string><string
xsi:type
="xs:string">Hello, punk</string><string xsi:type="xs:string">Hello,
punk</strin
g><string xsi:type="xs:string">Hello,
punk</string></say_helloResult></say_hello
Response></SOAP-ENV:Body></SOAP-ENV:Envelope>
WARNING:suds.umx.typed:attribute (type) type, not-found
(stringArray){
_type = "tns:stringArray"
string[] =
"Hello, punk",
"Hello, punk",
"Hello, punk",
"Hello, punk",
"Hello, punk",
}
*********************************
2nd Example
********************************
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
client= Client("http://localhost:7889/wsdl",cache=None)
print 'myclient',client
e = client.factory.create("ns0:say_hello")
print ' i am E',e
e.name = "punk"
e.times = 3
print 'I am E 2',e
client.service.say_hello(e)
E:\soaplib-0.8.1\examples>test_suds2.py
DEBUG:suds.transport.http:opening (http://localhost:7889/wsdl)
mycleint
Suds ( https://fedorahosted.org/suds/ ) version: 0.3.9 GA build:
R659-20100219
Service ( HelloWorldService ) tns="HelloWorldService.HelloWorldService"
Prefixes (1)
ns0 = "HelloWorldService.HelloWorldService"
Ports (1):
(HelloWorldService)
Methods (1):
say_hello(xs:string name, xs:integer times, )
Types (3):
say_hello
say_helloResponse
stringArray
i am E (say_hello){
name = None
times = None
}
I am E 2 (say_hello){
name = "punk"
times = 3
}
DEBUG:suds.transport.http:sending:
URL:http://localhost:7889/wsdl
HEADERS: {'SOAPAction': u'"say_hello"', 'Content-Type': 'text/xml',
'Content-typ
e': 'text/xml', 'Soapaction': u'"say_hello"'}
MESSAGE:
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:n
s1="HelloWorldService.HelloWorldService" xmlns:xsi="
http://www.w3.org/2001/XMLSc
hema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
****************************************
his I think shows the problem
****************************************
<ns0:Body>
<ns1:say_hello>
<name>
<name>punk</name>
<times>3</times>
</name>
<times/>
</ns1:say_hello>
</ns0:Body>
************************************************
</SOAP-ENV:Envelope>
ERROR:suds.client:<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:n
s1="HelloWorldService.HelloWorldService" xmlns:xsi="
http://www.w3.org/2001/XMLSc
hema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
******************************************
This I think shows the problem
*****************************************
<ns0:Body>
<ns1:say_hello>
<name>
<name>punk</name>
<times>3</times>
</name>
<times/>
</ns1:say_hello>
</ns0:Body>
</SOAP-ENV:Envelope>
Traceback (most recent call last):
File "E:\soaplib-0.8.1\examples\test_suds2.py", line 13, in <module>
client.service.say_hello(e)
File "E:\python-suds-0.3.9\suds\client.py", line 539, in __call__
return client.invoke(args, kwargs)
File "E:\python-suds-0.3.9\suds\client.py", line 598, in invoke
result = self.send(msg)
File "E:\python-suds-0.3.9\suds\client.py", line 633, in send
result = self.failed(binding, e)
File "E:\python-suds-0.3.9\suds\client.py", line 684, in failed
r, p = binding.get_fault(reply)
File "E:\python-suds-0.3.9\suds\bindings\binding.py", line 238, in
get_fault
raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'range() integer end argument expected,
got
NoneType.'
E:\soaplib-0.8.1\examples>
14 years
suds client and soaplib
by John Aherne
Sorry about these posts.
They kept being rejected with strange problems.
But I think I have already answered my question by reading the
documentation.
I should not be doing this for simple types.
Regards
John Aherne
14 years
Undelivered Mail Returned to Sender
by Mail Delivery System
This is the mail system at host smtp4.fastdnsnetwork.com.
I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.
For further assistance, please send mail to <postmaster>
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
The mail system
<sbi4833(a)cal3.vsnl.net.in>: host mta3.vsnl.net[203.200.235.143] said: 550 5.1.1
unknown or illegal alias: sbi4833(a)cal3.vsnl.net.in (in reply to RCPT TO
command)
14 years
suds client and soaplib
by John Aherne
I am using the soaplib trivial helloworld.py service example.
I can call soaplib from suds using simple types as the first example shows
below.
I pass 2 simple types a name and an integer value. And I get the response
repeated the number of times of the integer value.
But I am having a problem with calling soaplib from suds using the
client.factory_create method.
This you can see in the 2nd example.
Looking at the log output it seems that it is SUDS that has the problem -
but I am no expert on this.
It looks like it is trying to create a structure for a complex type and to
me it seems like it is not doing it correctly.
It could be I'm doing this all wrong. And I should be sticking to avoiding
the client factory for this type of message.
But I thought I would check and see if someone can give me some pointers as
to what I should be doing.
Needless to say I am not that well up in soap messages
Thanks for any info
John Aherne
************************************
1st example
************************************
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
client= Client("http://localhost:7889/wsdl",cache=None)
print client
print client.service.say_hello("punk",5)
E:\soaplib-0.8.1\examples>test_suds.py
Suds ( https://fedorahosted.org/suds/ ) version: 0.3.9 GA build:
R659-20100219
Service ( HelloWorldService ) tns="HelloWorldService.HelloWorldService"
Prefixes (1)
ns0 = "HelloWorldService.HelloWorldService"
Ports (1):
(HelloWorldService)
Methods (1):
say_hello(xs:string name, xs:integer times, )
Types (3):
say_hello
say_helloResponse
stringArray
DEBUG:suds.client:sending to (http://localhost:7889/wsdl)
message:
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:n
s1="HelloWorldService.HelloWorldService" xmlns:xsi="
http://www.w3.org/2001/XMLSc
hema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns1:say_hello>
<name>punk</name>
<times>5</times>
</ns1:say_hello>
</ns0:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': u'"say_hello"', 'Content-Type':
'text
/xml'}
DEBUG:suds.client:http succeeded:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:S
OAP-ENV="http://schemas.xmlsoap.org/soap/envelope/
"><SOAP-ENV:Body><say_helloRes
ponse><say_helloResult type="tns:stringArray"><string
xsi:type="xs:string">Hello
, punk</string><string xsi:type="xs:string">Hello, punk</string><string
xsi:type
="xs:string">Hello, punk</string><string xsi:type="xs:string">Hello,
punk</strin
g><string xsi:type="xs:string">Hello,
punk</string></say_helloResult></say_hello
Response></SOAP-ENV:Body></SOAP-ENV:Envelope>
WARNING:suds.umx.typed:attribute (type) type, not-found
(stringArray){
_type = "tns:stringArray"
string[] =
"Hello, punk",
"Hello, punk",
"Hello, punk",
"Hello, punk",
"Hello, punk",
}
*********************************
2nd Example
********************************
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
client= Client("http://localhost:7889/wsdl",cache=None)
print 'myclient',client
e = client.factory.create("ns0:say_hello")
print ' i am E',e
e.name = "punk"
e.times = 3
print 'I am E 2',e
client.service.say_hello(e)
E:\soaplib-0.8.1\examples>test_suds2.py
DEBUG:suds.transport.http:opening (http://localhost:7889/wsdl)
mycleint
Suds ( https://fedorahosted.org/suds/ ) version: 0.3.9 GA build:
R659-20100219
Service ( HelloWorldService ) tns="HelloWorldService.HelloWorldService"
Prefixes (1)
ns0 = "HelloWorldService.HelloWorldService"
Ports (1):
(HelloWorldService)
Methods (1):
say_hello(xs:string name, xs:integer times, )
Types (3):
say_hello
say_helloResponse
stringArray
i am E (say_hello){
name = None
times = None
}
I am E 2 (say_hello){
name = "punk"
times = 3
}
DEBUG:suds.transport.http:sending:
URL:http://localhost:7889/wsdl
HEADERS: {'SOAPAction': u'"say_hello"', 'Content-Type': 'text/xml',
'Content-typ
e': 'text/xml', 'Soapaction': u'"say_hello"'}
MESSAGE:
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:n
s1="HelloWorldService.HelloWorldService" xmlns:xsi="
http://www.w3.org/2001/XMLSc
hema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
****************************************
his I think shows the problem
****************************************
<ns0:Body>
<ns1:say_hello>
<name>
<name>punk</name>
<times>3</times>
</name>
<times/>
</ns1:say_hello>
</ns0:Body>
************************************************
</SOAP-ENV:Envelope>
ERROR:suds.client:<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:n
s1="HelloWorldService.HelloWorldService" xmlns:xsi="
http://www.w3.org/2001/XMLSc
hema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
******************************************
This I think shows the problem
*****************************************
<ns0:Body>
<ns1:say_hello>
<name>
<name>punk</name>
<times>3</times>
</name>
<times/>
</ns1:say_hello>
</ns0:Body>
</SOAP-ENV:Envelope>
Traceback (most recent call last):
File "E:\soaplib-0.8.1\examples\test_suds2.py", line 13, in <module>
client.service.say_hello(e)
File "E:\python-suds-0.3.9\suds\client.py", line 539, in __call__
return client.invoke(args, kwargs)
File "E:\python-suds-0.3.9\suds\client.py", line 598, in invoke
result = self.send(msg)
File "E:\python-suds-0.3.9\suds\client.py", line 633, in send
result = self.failed(binding, e)
File "E:\python-suds-0.3.9\suds\client.py", line 684, in failed
r, p = binding.get_fault(reply)
File "E:\python-suds-0.3.9\suds\bindings\binding.py", line 238, in
get_fault
raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'range() integer end argument expected,
got
NoneType.'
14 years