tags:

views:

288

answers:

2

I'm trying to get results from a SOAP service called Chrome ADS (for vehicle data). They provided php and Java samples, but I need python (our site is in Django). My question is:

What should I be passing as a request to the SOAP service when using wsdl2py-generated classes?

Following the examples I'm using a DataVersionsRequest object as the request parameter, but the code generated by wsdl2py seems to want a getDataVersions object, and there's something like that defined at the bottom of the generated _client.py file. But that too seems to throw an error. So I'm not sure what I should be passing as the request obj. Any suggestions?

$sudo apt-get install python-zsi
$wsdl2py http://platform.chrome.com/***********
$python 
>>> url = "http://platform.chrome.com/***********"
>>> from AutomotiveDescriptionService6_client import *
>>> from AutomotiveDescriptionService6_types import *
>>> locator = AutomotiveDescriptionService6Locator()
>>> service = locator.getAutomotiveDescriptionService6Port()
>>> locale = ns0.Locale_Def('locale')
>>> locale._country="US"
>>> locale._language="English"
>>> acctInfo = ns0.AccountInfo_Def('accountInfo')
>>> acctInfo._accountNumber=*****
>>> acctInfo._accountSecret="*****"
>>> acctInfo._locale = locale
>>> dataVersionsRequest = ns0.DataVersionsRequest_Dec()
>>> dataVersionsRequest._accountInfo = acctInfo
>>> service.getDataVersions(dataVersionsRequest)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "AutomotiveDescriptionService6_client.py", line 36, in getDataVersions
    raise TypeError, "%s incorrect request type" % (request.__class__)
TypeError: <class 'AutomotiveDescriptionService6_types.DataVersionsRequest_Dec'> incorrect request type
>>> dataVersionsRequest = getDataVersions
>>> dataVersionsRequest._accountInfo = acctInfo
>>> service.getDataVersions(dataVersionsRequest)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "AutomotiveDescriptionService6_client.py", line 36, in getDataVersions
    raise TypeError, "%s incorrect request type" % (request.__class__)
AttributeError: class DataVersionsRequest_Holder has no attribute '__class__'
>>> quit()
$cat AutomotiveDescriptionService6_client.py
.....
# Locator
class AutomotiveDescriptionService6Locator:
    AutomotiveDescriptionService6Port_address = "http://platform.chrome.com:80/AutomotiveDescriptionService/AutomotiveDescriptionService6"
    def getAutomotiveDescriptionService6PortAddress(self):
        return AutomotiveDescriptionService6Locator.AutomotiveDescriptionService6Port_address
    def getAutomotiveDescriptionService6Port(self, url=None, **kw):
        return AutomotiveDescriptionService6BindingSOAP(url or AutomotiveDescriptionService6Locator.AutomotiveDescriptionService6Port_address, **kw)

# Methods
class AutomotiveDescriptionService6BindingSOAP:
    def __init__(self, url, **kw):
        kw.setdefault("readerclass", None)
        kw.setdefault("writerclass", None)
        # no resource properties
        self.binding = client.Binding(url=url, **kw)
        # no ws-addressing

    # op: getDataVersions
    def getDataVersions(self, request, **kw):
        if isinstance(request, getDataVersions) is False:
            raise TypeError, "%s incorrect request type" % (request.__class__)
        # no input wsaction
        self.binding.Send(None, None, request, soapaction="", **kw)
        # no output wsaction
        response = self.binding.Receive(getDataVersionsResponse.typecode)
        return response
.....
getDataVersions = GED("urn:description6.kp.chrome.com", "DataVersionsRequest").pyclass

Also, as an aside, I'm not sure that the strings I'm passing to the pname parameter are correct, I assume that those are the ones I see inside the XML when I explore the service with SOAP UI, right?

A: 

You probably need to be instantiating your definition objects and then populating them. Look for type == pyclass_type objects associated with the request you're wanting to make and instantiate them.

e.g. (just guessing)

>>> versionrequest = getDataVersions()
>>> versionrequest.AccountInfo = versionrequest.new_AccountInfo()
>>> versionrequest.AccountInfo.accountNumber = "123"
>>> versionrequest.AccountInfo.accountSecret = "shhhh!"
>>> service.getDataVersions(versionrequest)

I found that the code generated by wsdl2py was too slow for my purposes. Good luck.

MattH
hmm, so is it faster to just use SOAPpy after all? I tried wsdl2py because when I tried passing SOAPpy a dict it errored out. I'm a little lost on how to proceed with teaching myself SOAP, and implementing it for this project.... on a deadline.
hendrixski
didn't seem to work:-(
hendrixski
Yeah, it's a steep learning curve. Have a look at https://fedorahosted.org/suds/ while I try to remember where that "Where was this when I was trying to understand SOAP?!" document I read recently is. It might have been on the suds site.
MattH
Seconding Suds, with the caveat I just found it yesterday. I was getting similar errors from SOAPpy, but Suds had no problem parsing stuff.
Tom
gah, I was wondering what that new_accountInfo() method was.... You need to run wsdl2py with the --complexTypes argument in order to get those. Otherwise it's prematurely optimized to not include those useful methods.That's what was missing all this time, one flag!
hendrixski
+1  A: 

It looks like you might be passing a class to service.getDataVersions() the second time instead of an instance (it can't be an instance if it doesn't have _class_).

What's happening is isinstance() returns false, and in the process of trying to raise a type error, an attribute error gets raised instead because it's trying to access _class_ which apparently doesn't exist.

What happens if you try:

>>> dataVersionsRequest = getDataVersions**()**
>>> dataVersionsRequest._accountInfo = acctInfo
>>> service.getDataVersions(dataVersionsRequest)

?

Based on the line:

if isinstance(request, getDataVersions) is False:
            raise TypeError, "%s incorrect request type" % (request.__class__)

it definitely looks like you should be passing an instance of getDataVersions, so you're probably on the right track.

Seán Hayes
Yeah, that seemed to fix it... now on to the next error: http://stackoverflow.com/questions/2382650/wsdl2py-complextypes
hendrixski
ah, and for anybody else reading this in the future, RUN WSDL2PY WITH THE --COMPLEXTYPE FLAG!!!You'll discover it creates more methods inside of each request object, that allow you to create them from the request object itself.
hendrixski