suds-community / suds

Suds is a lightweight SOAP python client for consuming Web Services. A community fork of the jurko fork.
https://suds.readthedocs.io/
GNU Lesser General Public License v3.0
173 stars 56 forks source link

AttributeError: 'Document' object has no attribute 'set' #65

Closed iwkse closed 2 years ago

iwkse commented 2 years ago

Hi, I'm adding this issue here to speed up the process, I don't believe it's a suds bug, so that's more like a question. I'm processing some shipment GLS API to, close shipment with the format like:

<info>
 <SedeGls>XX</SedeGls>
 <CodiceClienteGls>xxx</CodiceClienteGls>
 <PasswordClienteGls>xxx</PasswordClienteGls>
 <Parcel>
   <NumeroDiSpedizioneGLSDaConfermare>11111111</NumeroDiSpedizioneGlsDaConfermare>
 </Parcel>
</info>

Here I get an error:

[2021-12-14 11:48:27,472] {log.py:224} ERROR - Internal Server Error: /gls/process
Traceback (most recent call last):
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/rest_framework/decorators.py", line 50, in handler
    return func(*args, **kwargs)
  File "/home/corrieri/corrieri/Palumbix/Palumbix/views.py", line 96, in glsProcessShipment
    response = close_shipments_by_number(account.SedeGls,
  File "/home/corrieri/corrieri/Palumbix/gls/utils.py", line 52, in close_shipments_by_number
    response = sp.service.CloseWorkDayByShipmentNumber(data)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/client.py", line 566, in __call__
    return client.invoke(args, kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/client.py", line 703, in invoke
    soapenv = binding.get_message(self.method, args, kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/bindings/binding.py", line 122, in get_message
    content = self.bodycontent(method, args, kwargs)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/bindings/document.py", line 95, in bodycontent
    parse_args(method.name, self.param_defs(method), args, kwargs,
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/argparser.py", line 83, in parse_args
    return arg_parser(args, kwargs, extra_parameter_errors)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/argparser.py", line 108, in __call__
    self.__process_parameters()
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/argparser.py", line 299, in __process_parameters
    self.__process_parameter(*pdef)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/argparser.py", line 293, in __process_parameter
    self.__external_param_processor(param_name, param_type,
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/bindings/document.py", line 87, in add_param
    p = self.mkparam(method, pdef, value)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/bindings/document.py", line 129, in mkparam
    return super(Document, self).mkparam(method, pdef, object)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/bindings/binding.py", line 244, in mkparam
    return marshaller.process(content)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/mx/core.py", line 55, in process
    self.append(document, content)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/mx/core.py", line 68, in append
    self.appender.append(parent, content)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/mx/appender.py", line 86, in append
    appender.append(parent, content)
  File "/home/corrieri/corrieri/venv/lib/python3.9/site-packages/suds/mx/appender.py", line 179, in append
    parent.set(attr, value)
AttributeError: 'Document' object has no attribute 'set'

That's raised in the PrimitiveAppender class from suds/mx/appender.py

 class PrimitiveAppender(Appender):
     """
     An appender for python I{primitive} types.
     """

     def append(self, parent, content):
         if content.tag.startswith('_'):
             attr = content.tag[1:]
             value = tostr(content.value)
             if value:
                 parent.set(attr, value)
         else:
             child = self.node(content)
             child.setText(tostr(content.value))
             parent.append(child)
<s:element name="CloseWorkDay">
        <s:complexType>
           <s:sequence>
              <s:element minOccurs="0" maxOccurs="1" name="XMLCloseInfoParcel" type="s:string"/>
           </s:sequence>
        </s:complexType>
</s:element>
<s:element name="CloseWorkDayByShipmentNumber">
        <s:complexType>
           <s:sequence>
              <s:element minOccurs="0" maxOccurs="1" name="_xmlRequest" type="s:string"/>
           </s:sequence>
        </s:complexType>
</s:element>

The difference I see up here with these two methods,

The name is "_xmlRequest"

Here parent is a suds.sax.document.Document object and indeed it doesn't have a set method as this class doesn't extend the suds.sax.element.Element class, which I believe should be there instead.

It doesn't seems my XML request is wrong, I don't get it. Do you have any hints?

iwkse commented 2 years ago

I think it's actually a suds bug, I've implemented the call with requests passing the same data and it's successful

phillbaker commented 2 years ago

Hello, thanks for opening an issue. In order to investigate this further, we'll need the following:

Please note: if these can't be provided, we'll have to close this issue unfortunately as incomplete.

iwkse commented 2 years ago

Hi, the url is that one but the access is not public and it's required user and password that I cannot provide. I can provide a code snippet, as it's basically just passing the xml to the method and executing it. As for the version, I'm using the 1.0.0. Right now I'm not using suds for that call, I just commented and workaround with a post request call which it works. Maybe if you can give me some hints about why it searches for xmlRequest and what it means I can try to find it out myself. Because for all other methods there's no issue and I've noticed they all have name that doesn't start with Thank you

phillbaker commented 2 years ago

Hello, I believe this is similar to https://github.com/suds-community/suds/issues/30, which also described issues of passing XML in an attribute with a leading underscore.

phillbaker commented 2 years ago

Archeology of this: