suds-py3¶
Suds is a lightweight SOAP python client that provides a service proxy for Web Services.
Overview¶
The goal of suds is to present an RPC-‘like’ interface into soap-based web services. This means that in most cases, users do not need to be concerned with the complexities of the WSDL and referenced schemas. Regardless of which soap message style is specified, the signature of the service methods remain the same. Uses that do examine the WSDL will notice that even with the ‘document’ soap message style, the signature of each method resembles an RPC. The method signature contains the contents of the ‘document’ defined for the message instead of the document itself.
- No class generation
- Provides an object-like API.
- Reads wsdl at runtime for encoding/decoding
- Provides for the following SOAP (style) binding/encoding:
- Document/Literal
- RPC/Literal
- RPC/Encoded (section 5)
The goal of suds is to present an RPC-‘like’ interface into soap-based web services. This means that in most cases, users do not need to be concerned with the complexities of the WSDL and referenced schemas. Regardless of which soap message style is specified, the signature of the service methods remain the same. Uses that do examine the WSDL will notice that even with the ‘document’ soap message style, the signature of each method resembles an RPC. The method signature contains the contents of the ‘document’ defined for the message instead of the document itself.
Logging¶
The ‘suds’ package use the Python standard lib logging package, all messages are at level DEBUG or ERROR.
To register a console handler you can use basicConfig:
#!python import logging logging.basicConfig(level=logging.INFO)
Once the console handler is configured, the user can enable module specific debugging doing the following:
logging.getLogger(desired package>).setLevel(logging.desired-level>)
A common example (show sent/received soap messages):
#!python logging.getLogger('suds.client').setLevel(logging.DEBUG)
Suggested modules for debugging:
Set the logging level to ‘DEBUG’ on this module to see more details about soap messages (in & out) and http headers.
Basic Usage¶
The ‘suds’ [suds.client.Client-class.html Client] class provides a consolidated API for consuming web services. The object contains (2) sub-namespaces:
The [suds.client.Service-class.html service] namespace provides a proxy for the consumed service. This object is used to invoke operations (methods) provided by the service endpoint.
The [suds.client.Factory-class.html factory] namespace provides a factory that may be used to create instances of objects and types defined in the WSDL.
You will need to know the url for WSDL for each service used. Simply create a client for that service as follows:
#!python from suds.client import Client url = 'http://localhost:7080/webservices/WebServiceTestBean?wsdl' client = Client(url)
You can inspect service object with: __str__() as follows to get a list of methods provide by the service:
#!python print client Suds - version: 1.3.3.1 build: IN 20180220 Service (WebServiceTestBeanService) tns="http://test.server.enterprise.rhq.org/" Prefixes (1): ns0 = "http://test.server.enterprise.rhq.org/" Ports (1): (Soap) Methods: addPerson(Person person, ) echo(xs:string arg0, ) getList(xs:string str, xs:int length, ) getPercentBodyFat(xs:string name, xs:int height, xs:int weight) getPersonByName(Name name, ) hello() testExceptions() testListArg(xs:string[] list, ) testVoid() updatePerson(AnotherPerson person, name name, ) Types (23): Person Name Phone AnotherPerson
See example of service with multiple ports below.
The sample output lists that the service named WebServiceTestBeanService has methods such as getPercentBodyFat() and addPerson() .
Simple Arguments¶
Let’s start with the simple example. The getPercentBodyFat() method has the signature of getPercentBodyFat(‘xs:string’ name, ‘xs:int’ height, ‘xs:int’ weight) . In this case, the parameters are ‘simple’ types. That is, they not objects. This method would be invoked as follows:
#!python result = client.service.getPercentBodyFat('jeff', 68, 170) print result You have 21% body fat. #!python result = client.service.getPercentBodyFat(name='jeff', height=68, weight=170) print result You have 21% body fat. #!python d = dict(name='jeff', height=68, weight=170) result = client.service.getPercentBodyFat(**d) print result You have 21% body fat.
Complex Arguments¶
The addPerson() method takes a ‘person’ argument of type: ‘Person’ and has a signature of: addPerson(‘Person’ person, ) where parameter type is printed followed by it’s name.
There is a type (or class) named ‘person’ which is coincidentally the same name as the argument. Or in the case of getPercentBodyFat() the parameters are string of type xs:string and integer of type xs:int.
So, to create a ‘Person’ object to pass as an argument we need to get a person argument using the ‘factory’ sub-namespace as follows:
#!python person = client.factory.create('Person') print person (Person)= phone = [] age = NONE name(Name) = last = NONE first = NONE > >
As you can see, the object is created as defined by the WSDL. The list of phone number is empty so we’ll have to create a ‘Phone’ object:
#!python phone = client.factory.create('Phone') phone.npa = 202 phone.nxx = 555 phone.number = 1212
… and the name (Name object) and age need to be set and we need to create a name object first:
#!python name = client.factory.create('Name') name.first = 'Elmer' name.last = 'Fudd'
Now, let’s set the properties of our ‘Person’ object:
#!python person.name = name person.age = 35 person.phone = [phone]
#!python person.phone.append(phone)
… and invoke our method named addPerson() as follows:
#!python try: person_added = client.service.addPerson(person) except WebFault, e: print e
Users may not use python ‘dict’ for complex objects when they are subclasses (or extensions) of types defined in the wsdl/schema. In other words, if the schema defines a type to be an ‘Animal’ and you wish to pass a ‘Dog’ (assumes Dog ‘isa’ Animal), you may not use a ‘dict’ to represent the dog. In this case, suds needs to set the xsi:type=”Dog” but cannot because the python ‘dict’ does not provide enough information to indicate that it is a ‘Dog’ not an ‘Animal’. Most likely, the server will reject the request and indicate that it cannot instantiate a abstract ‘Animal’.
Complex Arguments Using Python (dict)¶
Just like the factory example, let’s assume the addPerson() method takes a ‘person’ argument of type: ‘Person’. So, to create a ‘Person’ object to pass as an argument we need to get a person object and we can do so by creating a simple python ‘dict’.:
According to the WSDL we know that the Person contains a list of Phone objects so we’ll need ‘dict’s for them as well:
#!python phone = 'npa':202, 'nxx':555, 'number':1212, >
… and the name (Name object) and age need to be set and we need to create a name object first:
#!python name = 'first':'Elmer', 'last':'Fudd' >
Now, let’s set the properties of our ‘Person’ object:
#!python person['name'] = name person['age'] = 35 person['phone'] = [phone,]
… and invoke our method named addPerson() as follows:
#!python try: person_added = client.service.addPerson(person) except WebFault, e: print e >>>
Faults¶
The Client can be configured to throw web faults as WebFault or to return a tuple (, ) instead as follows:
#!python client = client(url, faults=False) result = client.service.addPerson(person) print result ( 200, person . )
Options¶
The ‘suds’ [suds.client.Client-class.html client] has many that may be used to control the behavior of the library. Some are [suds.options.Options-class.html general options] and others are [suds.transport.options.Options-class.html transport options]. Although, the options objects are exposed, the preferred and supported way to set/unset options is through
- The [suds.client.Client-class.html Client] constructor
- The [suds.client.Client-class.html Client].set_options()
- The [suds.transport.Transport-class.html Transport] constructor(s).