I'm as eager to know as you are.
So i tried a few things and found the following to work, though
not as they way you'd like it to work:
----- [start service snippet]
@service.soap('GetQuote1', returns={'result':{'c':[{'c':float}],'b':
{'name':str,'value':str}}}, args={'symbol':str})
def stock_quote(symbol):
"Return stock quote info - everything is hardcoded..."
return dict(result={'c':[dict(c=1.0),dict(c=2.0)],
'b':dict(name='remco')})
----- [end service snippet]
which produces the following WSDL (snippet)
----- [start wsdl snippet]
<xsd:element name="GetQuote1Response">
<xsd:complexType>
<xsd:all>
<xsd:element name="result"
type="tns:GetQuote1Responseresult"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="GetQuote1Responseresult">
<xsd:all>
<xsd:element name="c"
type="tns:ArrayOfGetQuote1Responseresultc"/>
<xsd:element name="b" type="tns:GetQuote1Responseresultb"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="ArrayOfGetQuote1Responseresultc">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="c"
type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="GetQuote1Responseresultb">
<xsd:all>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="value" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
----- [end wsdl snippet]
now if you call this like
----- [start client snippet]
from gluon.contrib.pysimplesoap.client import SoapClient
print '*** crafting client '
client = SoapClient(wsdl='http://127.0.0.1:8000/welcome/default/call/
soap/?WSDL')
print '*** query '
print client.GetQuote1(symbol='google')
----- [end client snippet]
this *does* successfully output the following:
{'result': {'c': [{'c': 1.0}, {'c': 2.0}], 'b': {'name': 'remco'}}}
which is exactly what it should be.
What I've encountered and couldn't solve on my own:
* c Can't be a list of float, it has to be a list of a dictionary
with the key equal to the parent's key ('c' in this example).
Try some different things for yourself and see the errors.
* When returning result you have to return a complex type instead
of (the more intuitive):
return {'c':[dict(c=1.0),dict(c=2.0)], 'b':dict(name='remco')}
* Internally it seems to use Ordered dictionaries, but the actual
use of it is missing (somewhere in pysimplesoap\server.py@228)
so you might run into errors of the ordering of keys in
dictionaries. WSDL might be picky about it.
* depending on your client you might need to patch a little in the
source that produces the WSDL. I haven't tried a WSDL lint or
similar but i am not surprised if not all clients properly handle
pysimplesoaps wsdl because most clients are quite picky...
Hope this helps.
On 8 sep, 04:47, David Mitchell <[email protected]> wrote:
> Bump
>
> On 6 September 2011 19:13, David Mitchell <[email protected]> wrote:
>
>
>
>
>
>
>
> > Hello all,
>
> > I'm looking at using web2py to build a SOAP service to work as a test
> > harness for an infrastructure upgrade we're planning. Unfortunately, all
> > the web2py SOAP info I've found has been trivial services such as adding 2
> > numbers together - in my case, I need my SOAP server to be able to do
> > something more complicated.
>
> > The sort of complexity I need to build is something like
> >http://www.webservicex.com/stockquote.asmx?WSDL
> > When I query this service from suds, the code looks something like:
> > >>> import suds
> > >>> url = 'http://www.webservicex.com/stockquote.asmx?WSDL'
> > >>> client = suds.client.Client(url)
> > >>> print client
>
> > Suds (https://fedorahosted.org/suds/) version: 0.4 GA build:
> > R699-20100913
>
> > Service ( StockQuote ) tns="http://www.webserviceX.NET/"
> > Prefixes (0)
> > Ports (2):
> > (StockQuoteSoap)
> > Methods (1):
> > GetQuote(xs:string symbol, )
> > Types (0):
> > (StockQuoteSoap12)
> > Methods (1):
> > GetQuote(xs:string symbol, )
> > Types (0):
>
> > >>> client.service.GetQuote('IBM')
> > <StockQuotes><Stock><Symbol>IBM</Symbol><Last>166.98</Last><Date>9/2/2011</
> > Date><Time>4:00pm</Time><Change>0.00</Change><Open>N/A</Open><High>N/A</Hig
> > h><Low>N/A</Low><Volume>200</Volume><MktCap>199.4B</MktCap><PreviousClose>1
> > 66.98</PreviousClose><PercentageChange>0.00%</PercentageChange><AnnRange>12
> > 5.39
> > - 185.63</AnnRange><Earns>12.315</Earns><P-E>13.56</P-E><Name>International
> > Bus</Name></Stock></StockQuotes>
>
> > I figure my web2py controller code to do this would look something like:
>
> > from gluon.tools import Service
> > service = Service(globals())
>
> > @service.soap('GetQuote', returns={SOMETHING_HERE}, args={'symbol':str})
> > def stock_quote(stock):
> > "Return stock quote info - everything is hardcoded..."
> > symbol = "IBM"
> > last = 166.98
> > date = '9/2/2011'
> > quote_time = '4:00pm'
> > change = 0.00
> > #...
> > return SOMETHING_HERE
>
> > def call():
> > return service()
>
> > I'm trying to work out what the 2 SOMETHING_HERE pieces should look like in
> > the above code.
>
> > Could someone please point me in the right direction?
>
> > Thanks in advance
>
> > Dave M.