U
    H4fE                     @   s  d dl Z d dlZd dlmZ d dlmZ d dlmZmZm	Z	 d dl
mZmZmZ d dlmZ d dlmZmZmZ d dlmZ d d	lmZmZ d d
lmZmZ d dlmZ d dlmZm Z  ej!rd dl"m#Z# e $e%Z&G dd deZ'G dd de'Z(G dd de'Z)G dd deZ*dS )    N)etree)MultipartDecoder)nspluginswsa)FaultTransportErrorXMLSyntaxError)	parse_xml)as_qnameget_media_type
qname_attr)MessagePack)Binding	Operation)DocumentMessage
RpcMessage)process_xop)etree_to_stringurl_http_to_https)
Definitionc                       st   e Zd ZdZ fddZedd Zdd Zdd	d
Zdd Z	dd Z
dd Zdd ZdddZedd Z  ZS )SoapBindingzSoap 1.1/1.2 bindingc                    s    t  ||| || _|| _dS )a[  The SoapBinding is the base class for the Soap11Binding and
        Soap12Binding.

        :param wsdl:
        :type wsdl:
        :param name:
        :type name: string
        :param port_name:
        :type port_name: string
        :param transport:
        :type transport: zeep.transports.Transport
        :param default_style:

        N)super__init__	transportdefault_style)selfwsdlname	port_namer   r   	__class__ ;/tmp/pip-unpacked-wheel-04z2hmy8/zeep/wsdl/bindings/soap.pyr      s    zSoapBinding.__init__c                 C   s   |j d| jd}|dk	S )zCheck if this binding instance should be used to parse the given
        node.

        :param node: The node to match against
        :type node: lxml.etree._Element

        soap:binding
namespacesN)findnsmap)clsnode	soap_noder"   r"   r#   match.   s    	zSoapBinding.matchc                 O   s   |  |||\}}|S N)_create)r   	operationargskwargsenvelopehttp_headersr"   r"   r#   create_message:   s    zSoapBinding.create_messageNc                 C   s   |  |}|std| |j||}| || |j}|j}	|r|sN|jj}|jj	rnt
 ||	||\}}	t|||	||\}}	|jrt|jtr|jD ]}
|
||	\}}	qn|j||	\}}	|jjr|	|jj ||	fS )zCreate the XML document to send to the server.

        Note that this generates the soap envelope without the wsse applied.

        zOperation %r not found)get
ValueErrorcreate_set_http_headerscontentheadersZserviceZ_binding_optionsabstractZ
wsa_actionr   ZWsAddressingPluginZegressr   Zapply_egresswsse
isinstancelistapplysettingsZextra_http_headersupdate)r   r/   r0   r1   clientoptionsoperation_obj
serializedr2   r3   r<   r"   r"   r#   r.   >   s@    
       
zSoapBinding._createc           
      C   sP   | j |||||d\}}|j|d ||}| |}	|jjrB|S | ||	|S )a  Called from the service

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param options: The binding options
        :type options: dict
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param args: The args to pass to the operation
        :type args: tuple
        :param kwargs: The kwargs to pass to the operation
        :type kwargs: dict

        rB   rC   address)r.   r   post_xmlr5   r@   raw_responseprocess_reply
r   rB   rC   r/   r0   r1   r2   r3   responserD   r"   r"   r#   sendl   s        

zSoapBinding.sendc           
         sV   | j |||||d\}}|j|d ||I dH }|jjr>|S | |}	| ||	|S )a	  Called from the async service

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param options: The binding options
        :type options: dict
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param args: The args to pass to the operation
        :type args: tuple
        :param kwargs: The kwargs to pass to the operation
        :type kwargs: dict

        rF   rG   N)r.   r   rH   r@   rI   r5   rJ   rK   r"   r"   r#   
send_async   s         
  

zSoapBinding.send_asyncc              
   C   s  |j dkr|jsdS |j dkr8|js8td|j  |j d|jdd}t|}d}|dkrt|j||jpjd	}|jd
 j}t	|jdkrt
|jdd d}n|j}zt|| j|jd}	W nB tk
r }
 z$td|j |
|jf |j |jdW 5 d}
~
X Y nX |rt|	|rd}|jr(|j|	 t||	|j|\}	}|	jd| jd}|j dksd|dk	rp| |	|S ||	}|r|| |S |S )a  Process the XML reply from the server.

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param response: The response object returned by the remote server
        :type response: requests.Response

        )      N   z5Server returned HTTP status %d (no content available))status_codeContent-Typeztext/xmlzmultipart/relatedzutf-8r      )parts)r@   z?Server returned response (%s) with invalid XML: %s.
Content: %r)rR   r9   soap-env:Body/soap-env:Faultr%   )rR   r9   r   r:   r5   r   r   encodingrU   lenr   r
   r   r@   r	   r   r<   verifyr   Zapply_ingressr'   r(   process_errorrJ   Z	_set_root)r   rB   r/   rL   content_type
media_typeZmessage_packdecoderr9   docexcr3   
fault_noderesultr"   r"   r#   rJ      sf         

zSoapBinding.process_replyc                 C   s   t d S r-   )NotImplementedError)r   r^   r/   r"   r"   r#   rZ      s    zSoapBinding.process_errorFc                 C   s`   |j d| jd}|d kr&td d S |d}|rX|rXt|}||dkrXtd d|iS )Nzsoap:addressr%   z'No valid soap:address found for servicelocationz&Forcing soap:address location to HTTPSrG   )r'   r(   loggerdebugr5   r   warning)r   
xmlelementZforce_httpsZaddress_noderc   r"   r"   r#   process_service_port   s    


z SoapBinding.process_service_portc                 C   s   t |d|j}t |d|j}|jd| jd}|d}ddg}||krRtd| |d	d
}| |j||||}	|jd| jdD ]"}
tj	||
|	| jd}|	
| q|	S )a  

        Definition::

            <wsdl:binding name="nmtoken" type="qname"> *
                <-- extensibility element (1) --> *
                <wsdl:operation name="nmtoken"> *
                   <-- extensibility element (2) --> *
                   <wsdl:input name="nmtoken"? > ?
                       <-- extensibility element (3) -->
                   </wsdl:input>
                   <wsdl:output name="nmtoken"? > ?
                       <-- extensibility element (4) --> *
                   </wsdl:output>
                   <wsdl:fault name="nmtoken"> *
                       <-- extensibility element (5) --> *
                   </wsdl:fault>
                </wsdl:operation>
            </wsdl:binding>
        r   typer$   r%   r   z$http://schemas.xmlsoap.org/soap/httpz-http://www.w3.org/2003/05/soap/bindings/HTTP/z:The binding transport %s is not supported (only soap/http)styledocumentzwsdl:operation)r(   )r   Ztarget_namespacer'   r(   r5   rb   r   findallSoapOperationparseZ_operation_add)r)   definitionsrg   r   r   r+   r   Zsupported_transportsr   objr*   r/   r"   r"   r#   rn      s&    
zSoapBinding.parse)NN)F)__name__
__module____qualname____doc__r   classmethodr,   r4   r.   rM   rN   rJ   rZ   rh   rn   __classcell__r"   r"   r    r#   r      s   

.H
r   c                   @   s2   e Zd ZejejejejdZdd Z	dd Z
dS )Soap11BindingZsoapsoap-envr   Zxsdc                    sd   |j d| jd  d kr,tdd d t|d fdd}t|d|d|d	 j d
 jddd S )NrV   r%   Unknown fault occuredmessagecodeactordetailc                    s"    j |  jd}|d k	r|jS d S )Nr%   )r'   r(   textr   childr`   r"   r#   get_textD  s    z-Soap11Binding.process_error.<locals>.get_textZfaultstringZ	faultcodeZ
faultactorr   )r'   r(   r   r   )r   r^   r/   r   r"   r   r#   rZ   9  s    zSoap11Binding.process_errorc                 C   s   d|j d< d S )Nztext/xml; charset=utf-8rS   )r:   r   rE   r/   r"   r"   r#   r8   P  s    zSoap11Binding._set_http_headersN)rq   rr   rs   r   ZSOAP_11ZSOAP_ENV_11WSDLXSDr(   rZ   r8   r"   r"   r"   r#   rw   1  s   rw   c                   @   s2   e Zd ZejejejejdZdd Z	dd Z
dS )Soap12Bindingrx   c                    s   |j d| jd  d kr,tdd d t|d fdd} jd| jd} jd| jd}g } j d	| jd}|d k	r|j d
| jd}t|j|jd }	||	 |j d| jd}ql j d| jd}
t||d |
|dd S )NrV   r%   rz   r{   c                    s     | }|d k	r|jS d S r-   )r'   r   r   r   r"   r#   r   g  s    
z-Soap12Binding.process_error.<locals>.get_textzsoap-env:Reason/soap-env:Textzsoap-env:Code/soap-env:Valuezsoap-env:Code/soap-env:Subcodezsoap-env:Valuezsoap-env:Subcodezsoap-env:Detail)r|   r}   r~   r   subcodes)r'   r(   r   r   findtextr   r   append)r   r^   r/   r   r|   r}   r   Zsubcode_elementZsubcode_value_elementZsubcode_qnameZdetail_noder"   r   r#   rZ   \  sZ          
 zSoap12Binding.process_errorc                 C   s    d ddd|j g|jd< d S )Nz; zapplication/soap+xmlzcharset=utf-8zaction="%s"rS   )join
soapactionr:   r   r"   r"   r#   r8     s    zSoap12Binding._set_http_headersN)rq   rr   rs   r   ZSOAP_12ZSOAP_ENV_12r   r   r(   rZ   r8   r"   r"   r"   r#   r   T  s   3r   c                       sF   e Zd ZdZ fddZdd Zedd Zdd	 fd
dZ  Z	S )rm   z3Represent's an operation within a specific binding.c                    s$   t  || || _|| _|| _d S r-   )r   r   r(   r   rj   )r   r   bindingr(   r   rj   r    r"   r#   r     s    zSoapOperation.__init__c                 C   sF   t | jd d}|j|kr0td|j|jf | jrB| j|S d S )Nry   ZEnvelopezpThe XML returned by the server does not contain a valid {%s}Envelope root element. The root element found is %s )r   QNamer(   tagr	   	namespaceoutputZdeserialize)r   r2   Zenvelope_qnamer"   r"   r#   rJ     s    

zSoapOperation.process_replyc                 C   s   | d}|jd|jd}d}|dk	r@| d}| d|j}n|j}| |||||}	|dkrdt}
nt}
|D ]R}t|jj	}|dkrql|
j
|||	||d	}|d
kr||	j|j< qlt|	|| ql|	S )a  

        Definition::

            <wsdl:operation name="nmtoken"> *
                <soap:operation soapAction="uri"? style="rpc|document"?>?
                <wsdl:input name="nmtoken"? > ?
                    <soap:body use="literal"/>
               </wsdl:input>
               <wsdl:output name="nmtoken"? > ?
                    <-- extensibility element (4) --> *
               </wsdl:output>
               <wsdl:fault name="nmtoken"> *
                    <-- extensibility element (5) --> *
               </wsdl:fault>
            </wsdl:operation>

        Example::

            <wsdl:operation name="GetLastTradePrice">
              <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
              <wsdl:input>
                <soap:body use="literal"/>
              </wsdl:input>
              <wsdl:output>
              </wsdl:output>
              <wsdl:fault name="dataFault">
                <soap:fault name="dataFault" use="literal"/>
              </wsdl:fault>
            </operation>

        r   zsoap:operationr%   NZ
soapActionrj   Zrpc)inputr   fault)ro   rg   r/   r(   ri   r   )r5   r'   r(   r   r   r   r   r   r   	localnamern   faultsr   setattr)r)   ro   rg   r   r(   r   r+   actionrj   rp   Zmessage_classr*   Ztag_namemsgr"   r"   r#   rn     s4    "

zSoapOperation.parser   )ro   c                    st   t  | | j D ](\}}|| jjkr||| jj|  q| jrX| j|| jj | jrp| j|| jj	 d S r-   )
r   resolver   itemsr;   Zfault_messagesr   Zoutput_messager   Zinput_message)r   ro   r   r   r    r"   r#   r     s    zSoapOperation.resolve)
rq   rr   rs   rt   r   rJ   ru   rn   r   rv   r"   r"   r    r#   rm     s   
Frm   )+loggingtypinglxmlr   Z#requests_toolbelt.multipart.decoderr   Zzeepr   r   r   Zzeep.exceptionsr   r   r	   Zzeep.loaderr
   Z
zeep.utilsr   r   r   Zzeep.wsdl.attachmentsr   Zzeep.wsdl.definitionsr   r   Zzeep.wsdl.messagesr   r   Zzeep.wsdl.messages.xopr   Zzeep.wsdl.utilsr   r   TYPE_CHECKINGZzeep.wsdl.wsdlr   	getLoggerrq   rd   r   rw   r   rm   r"   r"   r"   r#   <module>   s*   
  #E