mvantellingen / python-zeep

A Python SOAP client
http://docs.python-zeep.org
Other
1.88k stars 586 forks source link

Failure to parse WSDL "No definition" ... "found" #320

Closed mattharrison closed 7 years ago

mattharrison commented 7 years ago
  1. The version of zeep (or if you are running master the commit hash/date)
    In [67]: zeep.__version__
    Out[75]: 
    '0.25.0'
  1. The WSDL you are using

System.wsdl found in

https://support.travelport.com/webhelp/uapi/Content/Resources/uAPI_WSDLschema_Release-V16.4.0.17.zip

  1. An example script

    
    import zeep

c = zeep.Client('Release-V16.4.0.17-V16.4/system_v32_0/System.wsdl')

$ python zeepfail.py Traceback (most recent call last): File "zeepfail.py", line 3, in c = zeep.Client('Release-V16.4.0.17-V16.4/system_v32_0/System.wsdl') File "/fbpy/env/lib/python3.6/site-packages/zeep/client.py", line 100, in init self.wsdl = Document(wsdl, self.transport) File "/fbpy/env/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 58, in init root_definitions.resolve_imports() File "/fbpy/env/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 195, in resolve_imports binding.resolve(self) File "/fbpy/env/lib/python3.6/site-packages/zeep/wsdl/definitions.py", line 102, in resolve self.port_type = definitions.get('port_types', self.port_name.text) File "/fbpy/env/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 175, in get raise IndexError("No definition %r in %r found" % (key, name)) IndexError: No definition '{http://www.travelport.com/service/system_v32_0}SystemPingPortType' in 'port_types' found

mvantellingen commented 7 years ago

The wsdl had multiple documents with duplicate target namespaces. These were (correctly?) ignored. I've just added support for duplicate tns so let me know if the master branch works (it should)

mattharrison commented 7 years ago

Awesome. Thanks for your help. I was able to make a successful SOAP call. Though I seem to have to go though a few hoops to get the ports working. Here is the code to generate 2 of my clients:

def tp_clients(username, password,
               address_prefix):
    infos = [('Release-V16.4.0.17-V16.4/air_v39_0/Air.wsdl',  'AirService', 'AirLowFareSearchPort'),
            ('Release-V16.4.0.17-V16.4/system_v32_0/System.wsdl','SystemService', 'SystemPingPort')]
    res = {}
    for path, service, port_name in infos:
        t = Transport()
        session = Session()
        session.auth = HTTPBasicAuth(username, password)
        proxy = True
        if proxy:
            url = config['PROXY_URL']
            os.environ['REQUESTS_CA_BUNDLE'] = config['PROXY_CA_BUNDLE']
            session.proxies = {'https': url}
        t.session = session
        fullpath = os.path.join(wsdl.__path__[0], path)
        history = HistoryPlugin()
        c = Client(wsdl=fullpath, transport=t, plugins=[history])
        port = c.bind(service, port_name)
        port._binding_options['address'] = '{}/{}'.format(address_prefix, service)
        res[port_name] = port
    return res

I'm assuming that I shouldn't be accessing _binding_options, but it didn't appear that this was exposed. Did I miss something?

mvantellingen commented 7 years ago

Cool. You can specify a custom endpoint by using th create_service call, see http://docs.python-zeep.org/en/master/client.html#creating-new-serviceproxy-objects

mvantellingen commented 7 years ago

I'm closing this ticket for now as it should be fixed. If there are still any issues then please let me know so that I can re-open the issue.

mvantellingen commented 7 years ago

Please read http://docs.python-zeep.org/en/master/reporting_bugs.html first.

kinoki commented 7 years ago

hi @mvantellingen, sorry if I deleted my previous comments as I think it was an error on the wsdl's part and not with zeep.

zeep version: 2.2.0 wsdl: https://gist.github.com/kinoki/4caabb8f595ac996538af2f799c44142 code ran: python -mzeep aramex-rates-calculator-wsdl.wsdl error: No definition '{http://ws.aramex.net/ShippingAPI/v1}Service_1_0' in 'port_types' found

I debugged the error from this and found out that one of the definitions missed a / xmlns:i0="http://ws.aramex.net/ShippingAPI/v1 that's why it fails when it checks if that key is in the container.

zeep/wsdl/wsdl.py

    def get(self, name, key, _processed=None):
        container = getattr(self, name)
        if key in container:
            return container[key]

I am not really that familiar with standards of wsdls but is this a valid error for them (be strict with / on urls) or should it also be handled by zeep?

Thank you. We really appreciate what you have done with zeep.

csotelo commented 6 years ago

Hi @mvantellingen I have the same issue, and is no possible to fix on bindings or proxy, since it appears at the moment of Client instance creation.

I mean, I need something like

`<?xml version='1.0' encoding='ISO-8859-1' standalone='no'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.sunat.gob.pe" xmlns:wsse="http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">

{{SunatRUC}}{{SunatUser}} {{SunatPass}} {{InvoiceFileName}} {{{InvoiceFileContent}}} ` Then I do something lik3: `client = Client(WDSL)` and, before go the the next line, the error appear as : `/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 214, in get raise IndexError("No definition %r in %r found" % (key, name)) IndexError: No definition '{http://service.sunat.gob.pe}billService' in 'port_types' found` I hope have a solution or find one on myself Thanks a lot
umiphos commented 5 years ago

Currently I'm having the same issue,

IndexError: No definition u'{http://service.sunat.gob.pe}billService' in 'port_types' 

When I try to get the service sendBill from https://e-factura.sunat.gob.pe/ol-ti-itcpfegem/billService?wsdl

If I came with a solution I will post the gist or script here

edynsoncoronado commented 5 years ago

post

I had the same problem, the error is because in the zeep library, exactly in zeep / wsdl / wsdl.py by line 202 def get(self, name, key, _processed=None): ... for definition in self.imports.values(): ... raise IndexError("No definition %r in %r found" % (key, name))

self.imports is {} so it does not enter the for and returns raise IndexError

what I did is modify a function before reaching the get, on line 231 def resolve_imports(self): ....for binding in self.bindings.values(): ++++ if self.imports: binding.resolve(self)

I added the "if" so that binding.resolve (self) only runs self.imports! = {} I hope it helps you

wdthiago commented 5 years ago

Hi, I'm having the same issue.

I get the error No definition ... in 'port_types' found when I try to create a Client instance. When I try to open the same WSDL file on SoapUI it works fine so I guess it is correctly formed.

Does anyone have solution?

jeffcondezo commented 5 years ago

The solution as "edysoncoronado" said is to change the wsdl.py file located in the Scripts folder of Python, on the line 236:

    for binding in self.bindings.values():
        if self.imports:
            binding.resolve(self)

as you can see we need to add the "if self.imports:" before "binding.resolve(self)"

And finally another point to considerate is to define port_type and name_service on Client.

client = Client('https://e-factura.sunat.gob.pe/ol-ti-itcpfegem/billService?wsdl',
                wsse=UsernameToken('20573431231MODDATOS', 'moddatos'), settings=settings,
                service_name='billService',
                port_name='BillServicePort')

I hope this can fix your issues.

MariusRettler commented 4 years ago

I am having the same issue and i was able to solve it with the solution @edynsoncoronado provided. Would it not make sense to implement this solution? And extend it to the other 4 for-loops aswell?

Because otherwise i am not able to create Client instances for some xml's.