function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Max BMax B 

Example of using Python & SOAPpy to invoke sfroce methods using Partner.WSDL

#!/usr/bin/env python
# Copyright (c) 2004 eBridge Software Inc. All rights reserved

from SOAPpy import WSDL
from SOAPpy import structType
from SOAPpy import headerType

# SOAPpy Configuration

#WSDL.Config.debug=1
WSDL.Config.namespaceStyle = '2001'

# For some reason SOAPpy treats SOAP Header as a data on dumping
# and uses "http://www.w3.org/1999/XMLSchema" namespace
# for validation instead of "http://schemas.xmlsoap.org/soap/envelope" namespace
# as you would expect that causes an exception in Types.anyType._validNamespaceURI
WSDL.Config.strictNamespaces = 0

email = "yourname@yourcompany.com"
psw = "yourpassword"
# URL to Partner.wsdl.xml
wsdl = "partner.wsdl"
# Create SOAP Proxy from WSDL
server = WSDL.Proxy(wsdl)

# Assigning sforce namespace to each sfroce method
#
# For some reason WSDLTools does not assign "urn:partner.soap.sforce.com"
# namespace to operations when it parses binding
for method in server.methods.itervalues():
method.namespace = "urn:partner.soap.sforce.com"

# Loggin in sforce using username and password
#
# Parameter names have to be explicitly specified, otherwise
# SOAPBuilder uses fake auto-incremented names
loginResult = server.login(username=email, password=psw)
print "The session id is:", loginResult.sessionId
print "The new server URL is:", loginResult.serverUrl
print "The user id is:", loginResult.userId
print

# Change the binding to a new endpoint
#
# For some reason SOAPpy replaces static soapproxy.proxy endpoint
# with service location for each operation
for method in server.methods.itervalues():
method.location = loginResult.serverUrl

# Assigning returned sessionId to SOAP header
ct = structType(data = {"sessionId" : loginResult.sessionId})
# SOAP Header support in SOAPpy does not allow us to access types declared
# in WSDL, so it has to be done manually
# The idea is from http://sourceforge.net/mailarchive/forum.php?thread_id=4990257&forum_id=1729
"""
#(06/27/05) seems to work fine with SF API 6 and SOAPpy 0.12.0
# Uncomment the double quotted block if you have SOAPpy > 0.12.0

#Ditch the standard namespaces
ct._validURIs = []
#Set the one we want to use
ct._ns = ("ns1", "urn:partner.soap.sforce.com")
"""
hd = headerType(data = {"SessionHeader" : ct})
server.soapproxy.header = hd

# Requesting sforce Server Timestamp
gstr = server.getServerTimestamp()
print "Server's timestamp is:", gstr.timestamp
print

# Requesting sforce user info for the user logged in
ui = server.getUserInfo()
print "User Name:", ui.userFullName
print "User Email:", ui.userEmail
print "User Language:", ui.userLanguage
print "User Locale:", ui.userLocale
print "User Time Zone:", ui.userTimeZone
print "User Default Currency ISO Code:", ui.userDefaultCurrencyIsoCode
print "User Id:", ui.userId
print "Orginization:", ui.organizationName
print "Orginization Id:", ui.organizationId
print "Multi-currency:", ui.organizationMultiCurrency
print "Currency Symbol:", ui.currencySymbol
print

# Listing sforce objects available for the user logged in
dgr = server.describeGlobal()
print "sforce objects available:"
for type in dgr.types:
print type

Message Edited by Max B on 06-27-2005 11:38 AM

chicchic

Hi Max,

Thanks for all the postings. I need some help to get things started. I first looked at the Python SF integration toolkit using ZSI, and realize that seems to be too complicated. Without trying, I decided to go the SOAPpy route.

I tried to use the sample codes, then I ran into the following problems:

Traceback (most recent call last):

File "sftest.py", line 10, in ?
s = SFConnect("./enterprise.wsdl").connect(u, p)
File "sfinit.py", line 23, in __init__
self.server = SFConnect.__S(wsdl) #WSDL.Proxy(wsdl)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/WSDL.py", line 57, in __init__
self.wsdl = reader.loadFromFile(wsdlsource)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/WSDLTools.py", line 51, in loadFromFile
wsdl = self.loadFromStream(file)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/WSDLTools.py", line 32, in loadFromStream
wsdl.load(document)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/WSDLTools.py", line 216, in load
schema = reader.loadFromNode(WSDLToolsAdapter(self), item)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 111, in loadFromNode
schema.load(reader)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 1028, in load
tp.fromDom(node)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 2101, in fromDom
self.content.fromDom(contents[indx])
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 1830, in fromDom
content[-1].fromDom(i)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 1630, in fromDom
self.setAttributes(node)
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 451, in setAttributes
self.attributes[k] = \
File "/home/soft/lib/python2.1/site-packages/SOAPpy/wstools/XMLSchema.py", line 2601, in __init__
tuple.__init__(self, args)
AttributeError: __init__

Do you experience anything similar to that? Any pointer? Thank you.

A note, we are running a very old version of Python (2.1.3), so I am also running SOAPpy 0.11.1. Upgrading the version is not an option for this project, maybe in the future...

Thank you very much for your help.

Best Regards

Elaine

Max BMax B
Hi Elaine,

I was using Python 2.3, SOAPpy 0.11.6, salesforce.com API 4.0 and partner.wsdl (the one that is common across all companies that use salesforce.com)

It looks like it fails when XMLSchema parses enterprise.wsdl file. You may want to try using partner.wsdl instead.

Also, for deep debugging I would recommend using Wing IDE (http://wingware.com/)

Max

Message Edited by Max B on 06-24-2005 02:20 PM

chicchic

Hi Max,

That is very helpful. After some tweak, I got pass the problem but fail in log. I got a Internal 500 error back without any information to help me further investigate. Here is the trace which I also output the payload before calling.

==================================================================

before sending payload, payload:

r = <httplib.HTTPS instance at 0x8c61e94>

data = <?xml version="1.0" encoding="UTF-8"?>

<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<SOAP-ENV:Body>

<ns1:login xmlns:ns1="urn:enterprise.soap.sforce.com" SOAP-ENC:root="1">

<password xsi:type="xsd:string">mypassword</password>

<username xsi:type="xsd:string">myusername</username>

</ns1:login>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

code= 500

msg= Internal Server Error

headers= Server: Resin/3.0.s040331

Content-Type: text/xml; charset=utf-8

Connection: close

Date: Fri, 24 Jun 2005 04:25:24 GMT

content-type= text/xml; charset=utf-8

data=

*** Incoming HTTP headers **********************************************

HTTP/1.? 500 Internal Server Error

Server: Resin/3.0.s040331

Content-Type: text/xml; charset=utf-8

Connection: close

Date: Fri, 24 Jun 2005 04:25:24 GMT

************************************************************************

Traceback (most recent call last):

File "sftest.py", line 10, in ?

s = SFConnect("./enterprise.wsdl").connect(u, p)

File "sfinit.py", line 40, in connect

lr = self.server.login(username=user, password=pw)

File "/home/soft/lib/python2.1/site-packages/SOAPpy/Client.py", line 421, in __call__

return self.__r_call(*args, **kw)

File "/home/soft/lib/python2.1/site-packages/SOAPpy/Client.py", line 443, in __r_call

self.__hd, self.__ma)

File "/home/soft/lib/python2.1/site-packages/SOAPpy/Client.py", line 345, in __call

config = self.config)

File "/home/soft/lib/python2.1/site-packages/SOAPpy/Client.py", line 242, in call

raise HTTPError(code, msg)

SOAPpy.Errors.HTTPError: <HTTPError 500 Internal Server Error>

==================================================================

Any suggestion? Thank you.  I have checked the login and password, which are correct.  So close yet so far...

Best Regards

Elaine

Max BMax B
Hi Elaine,


I have re-built partner.wsdl from salesforce.com and run the sample. Here is the trace:

=== Start dump ===
*** Outgoing HTTP headers **********************************************
POST /services/Soap/u/6.0 HTTP/1.0
Host: www.salesforce.com
User-agent: SOAPpy 0.12.0 (http://pywebsvcs.sf.net)
Content-type: text/xml; charset="UTF-8"
Content-length: 614
SOAPAction: "login"
************************************************************************
*** Outgoing SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<ns1:login xmlns:ns1="urn:partner.soap.sforce.com" SOAP-ENC:root="1">
<username xsi:type="xsd:string">username@mycompany.com</username>
<password xsi:type="xsd:string">mypass</password>
</ns1:login>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
************************************************************************
code= 200
msg= OK
headers= Server: Resin/3.0.s040331
Content-Type: text/xml; charset=utf-8
Connection: close
Date: Fri, 24 Jun 2005 15:42:02 GMT

content-type= text/xml; charset=utf-8
data= <?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<soapenv:Body>
<loginResponse xmlns="urn:partner.soap.sforce.com">
<result>
<passwordExpired>false</passwordExpired>
<serverUrl>https://na1-api.salesforce.com/services/Soap/u/6.0</serverUrl>
<sessionId>8TPjQ5MQQp7BIZgc4RSSMjNeYiqiUC.Pa55ual6Mv.WuxNx5RzQmTrmTj_IKGfScnNmpINuL6ASCBkgIgUv5PxhD2wYHcrlK4SNdGN37zi4=</sessionId>
<userId>00530000000dGDuAAM</userId>
<userInfo>
<currencySymbol>$</currencySymbol>
<organizationId>XXXXXXXXXXXXX</organizationId>
<organizationMultiCurrency>false</organizationMultiCurrency>
<organizationName>XXXXXXXXXXXXXXX</organizationName>
<userDefaultCurrencyIsoCode xsi:null="true"/>
<userEmail>username@mycompany.com</userEmail>
<userFullName>XXXXXXXXXXXXX</userFullName>
<userId>XXXXXXXXXXX</userId>
<userLanguage>en_US</userLanguage>
<userLocale>en_CA</userLocale>
<userTimeZone>America/New_York</userTimeZone>
</userInfo>
</result>
</loginResponse>
</soapenv:Body>
</soapenv:Envelope>
*** Incoming HTTP headers **********************************************
HTTP/1.? 200 OK
Server: Resin/3.0.s040331
Content-Type: text/xml; charset=utf-8
Connection: close
Date: Fri, 24 Jun 2005 15:42:02 GMT
************************************************************************
*** Incoming SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<soapenv:Body>
<loginResponse xmlns="urn:partner.soap.sforce.com">
<result>
<passwordExpired>false</passwordExpired>
<serverUrl>https://na1-api.salesforce.com/services/Soap/u/6.0</serverUrl>
<sessionId>8TPjQ5MQQp7BIZgc4RSSMjNeYiqiUC.Pa55ual6Mv.WuxNx5RzQmTrmTj_IKGfScnNmpINuL6ASCBkgIgUv5PxhD2wYHcrlK4SNdGN37zi4=</sessionId>
<userId>XXXXXXXXXXXXXX</userId>
<userInfo>
<currencySymbol>$</currencySymbol>
<organizationId>XXXXXXXX</organizationId>
<organizationMultiCurrency>false</organizationMultiCurrency>
<organizationName>XXXXXXXXXXXXX</organizationName>
<userDefaultCurrencyIsoCode xsi:null="true"/>
<userEmail>username@mycompany.com</userEmail>
<userFullName>XXXXXXXXXXXX</userFullName>
<userId>XXXXXXXXXXX</userId>
<userLanguage>en_US</userLanguage>
<userLocale>en_CA</userLocale>
<userTimeZone>America/New_York</userTimeZone>
</userInfo>
</result>
</loginResponse>
</soapenv:Body>
</soapenv:Envelope>
************************************************************************
The session id is: 8TPjQ5MQQp7BIZgc4RSSMjNeYiqiUC.Pa55ual6Mv.WuxNx5RzQmTrmTj_IKGfScnNmpINuL6ASCBkgIgUv5PxhD2wYHcrlK4SNdGN37zi4=
The new server URL is: https://na1-api.salesforce.com/services/Soap/u/6.0
The user id is: XXXXXXXXXXXXXXXXXX

=== Finish dump ===

I believe it may have something to do with SOAP Service End Point, there may not be a service processing your request. Check your WSDL:

<!-- Soap Service Endpoint -->
<service name="SforceService">
<documentation>Sforce SOAP API</documentation>
<port binding="tns:SoapBinding" name="Soap">
<soap:address location="https://www.salesforce.com/services/Soap/u/6.0"/>
</port>
</service>

Best regards,
Max
surfoussurfous
Setting a couple more SOAPpy config parameters will improve success using Python, SOAPpy and sforce.

Using Max's original example, near the top with similar lines, add:

WSDL.Config.simplify_objects = 1
WSDL.Config.typed = 0

simplify_objects auto-unpacks responses into Python dictionaries so you don't have to do it with the response objects' _asdict() call every time. This is especially nice when the response has nested structures, such as with describeSObject.

typed (among other things) affects how lists are passed when making SOAP calls. If types is true, lists elements are wrapped as an arrayType which the sforce web service does not like. As a result, you cannot do a retrieve on a list of object IDs, for example. Setting this to False (or 0) alters this behavior so that a list is sent as a series of like-named elements, in accordance the soap message examples found in the resources section of sforce.com.

Finally, when doing a multiple-ID retrieve (or delete, I presume), you must ensure that the ID list is unique. If a duplicate exists, SOAPpy sends a badly broken message to sforce which replies with an INVALID_SESSION_ID fault. This seems like a strange response and it makes no sense unless you look at the dreck that SOAPpy inadvertantly has sent.

--Kevin