pythonxmlwsdlsudszeep

Python Zeep AttributeError: 'NoneType' object has no attribute 'elements' [switching to suds-community]


This is a 2-part question, for the following code:

from zeep import Client
from datetime import datetime
import logging.config

logging.config.dictConfig({
    "version": 1,
    "formatters": {"verbose": {"format": "%(asctime)s # [%(name)s]: %(message)s"}},
    "handlers": {"console": {"level": "DEBUG", "class": "logging.StreamHandler", "formatter": "verbose"}},
    "loggers": {"zeep.transports": {"level": "DEBUG", "propagate": True, "handlers": ["console"]}}
})

client = Client("https://t-mobile.provisioning.blackberry.com/webservices/Provisioning?wsdl")

client.service._binding_options['address'] = "https://t-mobile.provisioning.blackberry.com/webservices/Provisioning"

ProvisionRequest = {
    "provisionRequest": {
        "body": [{
            "ProvisionReqEntity" : {            
                "items": [{
                    "ProvisionDataItem": {
                        "name": "MSISDN",   
                        "data": "123456789"
                    }
                }],
                "name": "subscriber"
            }
        }],
        "header": {
            "sender": {
                "id": "123",
                "loginId": "myLoginId",
                "name": "myName",
                "password": "myPassword"
            },
            "timeFormat": "CCYY-MM-DDThh:mm:ssZ",
            "timeStamp": datetime.now().astimezone().replace(microsecond=0).isoformat()
        },
        "productType": "BlackBerry",
        "transactionId": "123123123123",
        "transactionType": "Status",
        "version": "1.2"
    }
}

response = client.service.echoTest( **ProvisionRequest )
print(response)

1) I can't seem to make the request body match desired array structure for ProvisionReqEntity. Desired Request shall look like:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prov="http://www.blackberry.com/webservices/Provisioning" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
   <soapenv:Header/>
   <soapenv:Body>
      <prov:echoTest soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <provisionRequest xsi:type="java:ProvisionRequest" xmlns:java="java:provision.control.ari.comm.soap">
            <body xsi:type="java:ArrayOfProvisionReqEntity" soapenc:arrayType="java:ProvisionReqEntity[1]">
                <ProvisionReqEntity>
                   <name xsi:type="xsd:string">subscriber</name>
                   <items soapenc:arrayType="java:ProvisionDataItem[1]">
                      <ProvisionDataItem>
                         <name xsi:type="xsd:string">MSISDN</name>
                         <data xsi:type="xsd:string">123456789</data>
                      </ProvisionDataItem>
                   </items>
                </ProvisionReqEntity>
            </body>
            <header xsi:type="java:ProvisionReqHeader">
               <sender xsi:type="java:ProvisionSender">
                  <id xsi:type="xsd:string">123</id>
                  <loginId xsi:type="xsd:string">myLoginId</loginId>
                  <name xsi:type="xsd:string">myName</name>
                  <password xsi:type="xsd:string">myPassword</password>
               </sender>
               <timeFormat xsi:type="xsd:string">CCYY-MM-DDThh:mm:ssZ</timeFormat>
               <timeStamp xsi:type="xsd:string">${=new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(new Date())}</timeStamp>
            </header>
            <productType xsi:type="xsd:string">BlackBerry</productType>
            <transactionId xsi:type="xsd:string">123123123123</transactionId>
            <transactionType xsi:type="xsd:string">Status</transactionType>
            <version xsi:type="xsd:string">1.2</version>
         </provisionRequest>
      </prov:echoTest>
   </soapenv:Body>
</soapenv:Envelope>

However; Zeep shows the following for ProvisionReqEntity:

<ns1:body xmlns:ns1="java:provision.control.ari.comm.soap">
    <ProvisionReqEntity>
        <ns1:items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
        <ns1:name xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
        <ns1:optionalTokens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
        <ns1:subEntities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
        <ns1:type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
    </ProvisionReqEntity>
</ns1:body>

2) Why isn't Python / Zeep printing the response? The logger clearly shows I got a valid response.

Bonus Question: :-)

3) Is client.service._binding_options['address'] the recommended method to modify the endpoint?


Solution

  • I solved my problem by switching to suds-community.

    from suds.client import Client
    from datetime import datetime
    import logging
    
    logging.basicConfig(level=logging.INFO)
    logging.getLogger('suds.client').setLevel(logging.DEBUG)
    
    client = Client('https://t-mobile.provisioning.blackberry.com/webservices/Provisioning?wsdl')
    
    client.set_options(location='https://t-mobile.provisioning.blackberry.com/webservices/Provisioning')
    
    ProvisionRequest = {
        'body': [{
            'items': [{
                'name': "MSISDN",
                'data': "123456789"
            }],
            'name': "subscriber"
        }],
        'header': {
            'sender': {
                'id': "123",
                'loginId': "myLoginId",
                'name': "myName",
                'password': "myPassword"
            },
            'timeFormat': "CCYY-MM-DDThh:mm:ssZ",
            'timeStamp': datetime.now().astimezone().replace(microsecond=0).isoformat()
        },
        'productType': "BlackBerry",
        'transactionId': "123123123123",
        'transactionType': "Status",
        'version': "1.2"
    }
    
    response = client.service.echoTest( ProvisionRequest )
    print(response)