o
    gZd                     @   s   d Z ddlmZmZ ddlmZ ddlmZmZm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZ ddlZddlmZ dd	lmZmZmZ d
dlmZmZ d
dlmZm Z m!Z!m"Z" ddl#m$Z$m%Z% G dd dZ&G dd dZ'dS ), Class to work with Salesforce Metadata API     )	b64encode	b64decode)Path)AnyDictIOListMappingOptionalTupleUnion)ElementTree)ElementN)ServiceProxy)AnySimpleTypeComplexTypeCompoundValue   )Headerscall_salesforce)
DEPLOY_MSGCHECK_DEPLOY_STATUS_MSGCHECK_RETRIEVE_STATUS_MSGRETRIEVE_MSG)ClientSettingsc                   @   s  e Zd ZdZdededeeef de	fddZ
edee d	d
fddZdeded	efddZdee d	d
fddZdee d	eee ef fddZdee d	d
fddZdee d	d
fddZdeeeef  d	d
fddZdeded	d
fdd Zd	efd!d"Zd
S )#MetadataTypez"
    Salesforce Metadata Type
    nameservice	zeep_typesession_headerc                 C   s   || _ || _|| _|| _dS )a}  
        Initialize metadata type

        :param name: Name of metadata type
        :type name: str
        :param service: Zeep service
        :type service: zeep.proxy.ServiceProxy
        :param zeep_type: Zeep type object
        :type zeep_type: zeep.xsd.ComplexType or zeep.xsd.AnySimpleType
        :param session_header: Session Id header for Metadata API calls
        N)_name_service
_zeep_type_session_header)selfr   r   r    r!    r'   S/home/ubuntu/webapp/venv/lib/python3.10/site-packages/simple_salesforce/metadata.py__init__   s   
zMetadataType.__init__responsereturnNc                 C   s\   d}| D ]!}|j s%|d|j d7 }|jD ]}|d|j d|j d7 }qq|r,t|dS )ah  
        Parses SaveResult and DeleteResult objects to identify if there was
        an error, and raises exception accordingly

        :param response: List of zeep.objects.SaveResult or
        zeep.objects.DeleteResult objects
        :type response: list
        :raises Exception: If any Result object contains one or more error
        messages
         
z: (z, z), N)successfullNameerrors
statusCodemessage	Exception)r*   
err_stringresulterrorr'   r'   r(   _handle_api_response-   s   
z!MetadataType._handle_api_responseargskwargsc                 O   s   | j |i |S )z
        Creates a new object of this metadata type

        :param args: Parameters to pass to zeep.xsd.AnySimpleType
        :param kwargs: Parameters to pass to zeep.xsd.ComplexType
        :returns: An object of type self._name
        )r$   )r&   r9   r:   r'   r'   r(   __call__C   s   zMetadataType.__call__metadatac                 C   "   | j j|| jgd}| | dS )a  
        Performs a createMetadata call

        :param metadata: Array of one or more metadata components.
                         Limit: 10. (For CustomMetadata and CustomApplication
                         only, the limit is 200.)
                         You must submit arrays of only one type of
                         component. For example, you can submit an
                         array of 10 custom objects or 10 profiles, but not a
                         mix of both types.
        :type metadata: list
        _soapheadersN)r#   createMetadatar%   r8   r&   r<   r*   r'   r'   r(   createM   s   zMetadataType.create
full_namesc                 C   s0   | j j| j|| jgd}t|dkr|d S |S )aj  
        Performs a readMetadata call

        :param full_names: Array of full names of the components to read.
                           Limit: 10. (For CustomMetadata and
                           CustomApplication only, the limit is 200.)
                           You must submit arrays of only one type of
                           component. For example, you can submit an array
                           of 10 custom objects or 10 profiles, but not a mix
                           of both types.
        :type full_names: list
        :returns: A list of metadata components
        :rtype: list
        r>   r   r   )r#   readMetadatar"   r%   lenr&   rC   r*   r'   r'   r(   read^   s   zMetadataType.readc                 C   r=   )aR  
        Performs an updateMetadata call. All required fields must be passed
        for each component

        :param metadata: Array of one or more metadata components.
                         Limit: 10. (For CustomMetadata and CustomApplication
                         only, the limit is 200.)
                         You must submit arrays of only one type of
                         component. For example, you can submit an
                         array of 10 custom objects or 10 profiles, but not a
                         mix of both types.
        :type metadata: list
        r>   N)r#   updateMetadatar%   r8   rA   r'   r'   r(   updatet      zMetadataType.updatec                 C   r=   )aR  
        Performs an upsertMetadata call. All required fields must be passed
        for each component

        :param metadata: Array of one or more metadata components.
                         Limit: 10. (For CustomMetadata and CustomApplication
                         only, the limit is 200.)
                         You must submit arrays of only one type of
                         component. For example, you can submit an
                         array of 10 custom objects or 10 profiles, but not a
                         mix of both types.
        :type metadata: list
        r>   N)r#   upsertMetadatar%   r8   rA   r'   r'   r(   upsert   rJ   zMetadataType.upsertc                 C   s&   | j j| j|| jgd}| | dS )a)  
        Performs a deleteMetadata call

        :param full_names: Array of full names of the components to delete.
                           Limit: 10. (For CustomMetadata and
                           CustomApplication only, the limit is 200.)
                           You must submit arrays of only one type of
                           component. For example, you can submit an array
                           of 10 custom objects or 10 profiles, but not a mix
                           of both types.
        :type full_names: list
        r>   N)r#   deleteMetadatar"   r%   r8   rF   r'   r'   r(   delete   s
   zMetadataType.deleteold_full_namenew_full_namec                 C   s*   | j j| j||| jgd}| |g dS )z
        Performs a renameMetadata call

        :param old_full_name: The current component full name.
        :type old_full_name: str
        :param new_full_name: The new component full name.
        :type new_full_name: str
        r>   N)r#   renameMetadatar"   r%   r8   )r&   rO   rP   r6   r'   r'   r(   rename   s   	zMetadataType.renamec                 C   s   | j jd| j | jgdS )z^
        Performs a describeValueType call

        :returns: DescribeValueTypeResult
        z){http://soap.sforce.com/2006/04/metadata}r>   )r#   describeValueTyper"   r%   r&   r'   r'   r(   describe   s   
zMetadataType.describe)__name__
__module____qualname____doc__strr   r   r   r   r   r)   staticmethodr	   r   r8   r;   rB   rG   rI   rL   r   rN   rR   rU   r'   r'   r'   r(   r      s*    


"r   c                   @   s  e Zd ZdZdZdddZdejdeded	ed
e	de
e fddZdedefddZdefddZdee dee fddZdeeee f dededee
e e
e f fddZedeeee f defddZdededefdd Zed!edefd"d#Zdededee
e e
e e
eeef  e
eeef  f fd$d%Zdedd&fd'd(Z dededee
e e
e f fd)d*Z!ded+ededefd,d-Z"dededee
e e
e ee#eef  ef fd.d/Z$dededee
e e
e ee#ee
e f  f fd0d1Z%d&S )2SfdcMetadataApir   z/services/Soap/m/{version}z)http://schemas.xmlsoap.org/soap/envelope/z'http://soap.sforce.com/2006/04/metadata)soapenvmtsession
session_idinstancemetadata_urlheadersapi_versionc                 C   s   || _ || _|| _|| _|| _|| _d| _ttj	d }t
|  tdddd| _| jd| j| _| jd| jd	| _dS )
z Initialize and check session Nzmetadata.wsdlFT)strictxsd_ignore_sequence_order)settingsz8{http://soap.sforce.com/2006/04/metadata}MetadataBindingzns0:SessionHeader)	sessionId)r_   _session_id	_instancerb   rc   _api_version_deploy_zipr   __file__parentr   absoluteas_urir   _clientcreate_servicer#   get_elementr%   )r&   r_   r`   ra   rb   rc   rd   	wsdl_pathr'   r'   r(   r)      s0   	
zSfdcMetadataApi.__init__itemr+   c                 C   s   t || j| jd| | jS )Nzns0:)r   r#   rq   get_typer%   )r&   ru   r'   r'   r(   __getattr__   s   zSfdcMetadataApi.__getattr__c                 C   s   | j j| j| jgdS )zv
        Performs a describeMetadata call

        :returns: An object of zeep.objects.DescribeMetadataResult
        r>   )r#   describeMetadatark   r%   rT   r'   r'   r(   describe_metadata   s   
z!SfdcMetadataApi.describe_metadataqueriesc                 C   s   | j j|| j| jgdS )a=  
        Performs a listMetadata call

        :param queries: A list of zeep.objects.ListMetadataQuery that specify
        which components you are interested in.
                        Limit: 3
        :type queries: list
        :returns: List of zeep.objects.FileProperties objects
        :rtype: list
        r>   )r#   listMetadatark   r%   )r&   rz   r'   r'   r(   list_metadata   s
   zSfdcMetadataApi.list_metadatazipfilesandboxr:   c                 K   s~  | dd}| dd}| d}| d}| dd}| dd}	| d	d}
| d
d}| dd}| dd}d}||| j| |||||	|
||||d}|sZd|d< d|d< |rfd| d}||d< d}|rt| dkr|D ]
}|d| d7 }qt||d< tjdi |}ddd}t| jd d| j	| j
||d}t|jdd| jpd}t|jdd| jpd}||fS )z Kicks off async deployment, returns deployment id
        :param zipfile:
        :type zipfile:
        :param kwargs:
        :type kwargs:
        :return:
        :rtype:
        clientsimple_salesforce_metahelper	checkOnlyF	testLeveltestsignoreWarningsallowMissingFilesautoUpdatePackageperformRetrievepurgeOnDeleterollbackOnErrorT)r   r   rh   ZipFiler   r   r   r   r   r   r   r   singlePackagez<met:testLevel>z</met:testLevel>r,   runspecifiedtestsz<met:runTests>z</met:runTests>
text/xmldeploy)zContent-Type
SOAPActiondeployRequestPOSTurlmethodr_   rc   additional_headersdataz.soapenv:Body/mt:deployResponse/mt:result/mt:idNz1soapenv:Body/mt:deployResponse/mt:result/mt:stater'   )getri   _read_deploy_ziprZ   lowerr   formatr   rb   r_   rc   ET
fromstringtextfindtext_XML_NAMESPACES)r&   r}   r~   r:   r   r   r   r   r   r   r   r   r   r   r   
attributes
test_level	tests_tagtestrequestrc   r6   async_process_idstater'   r'   r(   r     sz   



zSfdcMetadataApi.deployc                 C   s@   t | drt | dr| d |  }nt|  }t| S )zY
        :param zipfile:
        :type zipfile:
        :return:
        :rtype:
        rG   seekr   )hasattrr   rG   r   
read_bytesr   decode)r}   rawr'   r'   r(   r   \  s
   	

z SfdcMetadataApi._read_deploy_zipr   c           
      K   s   | dd}|| j|dd}tjdi |}ddd}t| jd | d	| j| j||d
}t	|j
}|d| j}	|	du rEtd|j
 |	S )z Retrieves status for specified deployment id
        :param async_process_id:
        :type async_process_id:
        :param kwargs:
        :type kwargs:
        :return:
        :rtype:
        r   r   true)r   rh   asyncProcessIdincludeDetailsr   checkDeployStatuszContent-typer   deployRequest/r   r   z3soapenv:Body/mt:checkDeployStatusResponse/mt:resultN Result node could not be found: r'   )r   ri   r   r   r   rb   r_   rc   r   r   r   findr   r4   )
r&   r   r:   r   r   
mt_requestrc   resrootr6   r'   r'   r(   _retrieve_deploy_resultm  s2   z'SfdcMetadataApi._retrieve_deploy_resultvaluec                 C   s    zt | W S  ty   Y dS w )zGet component error countsr   )int
ValueError)r   r'   r'   r(   get_component_error_count  s
   
z)SfdcMetadataApi.get_component_error_countc                 K   s  | j |fi |}|dd| jpd}|dd| jpd}g }g }| |dd| j}|dks4|dkr|d| j}	|	D ],}
||
d	d| jpJd|
d
d| jpSd|
dd| jp\d|
dd| jpedd q=|d| j}	|	D ],}
||
dd| jpd|
dd| jpd|
dd| jpd|
dd| jpdd qs|dd| jpd|dd| jpd|dd| jpd|d}|dd| jpd|dd| jpd|dd| jpd|d}||||fS )z
        Checks whether deployment succeeded
        :param async_process_id:
        :type async_process_id:
        :param kwargs:
        :type kwargs:
        :return:
        :rtype:
        	mt:statusNzmt:stateDetailzmt:numberComponentErrorsr,   Failedr   zmt:details/mt:componentFailureszmt:componentTypemt:fileNamezmt:problemType
mt:problem)typefilestatusr3   z'mt:details/mt:runTestResult/mt:failureszmt:namezmt:methodNamez
mt:messagezmt:stackTrace)classr   r3   stack_tracezmt:numberComponentsTotalzmt:numberComponentsDeployed)total_countfailed_countdeployed_countr1   zmt:numberTestsTotalzmt:numberTestErrorszmt:numberTestsCompleted)r   r   completed_countr1   )r   r   r   r   findallappend)r&   r   r:   r6   r   state_detailunit_test_errorsdeployment_errorsr   failuresfailuredeployment_detailunit_test_detailr'   r'   r(   check_deploy_status  s   

z#SfdcMetadataApi.check_deploy_statusNc                 C   s$   |  |}tdtj|ddd dS )zQ Downloads Apex logs for unit tests executed during specified
        deployment z	response:zus-asciixml)encodingr   N)r   printr   tostring)r&   r   r6   r'   r'   r(   download_unit_test_logs  s   
z'SfdcMetadataApi.download_unit_test_logsc                 K   s4  | dd}| dd}t|tstdd}| drR| di D ]/}t| dtrN| di | }|d7 }|D ]
}|d	| d
7 }q:|d| d7 }q"td|| j| j||d}	tjdi |	}
ddd}t	| j
d | d| j| j||
d}t|jdd| jpd}t|jdd| jpd}||fS )z Submits retrieve request r   r   single_packageTzsingle_package must be boolr,   
unpackagedz<types>z	<members>z
</members>z<name>z</name></types>z(unpackaged metadata types must be a dict)r   rh   
apiVersionr   r   r   retriever   r   r   r   z0soapenv:Body/mt:retrieveResponse/mt:result/mt:idNz3soapenv:Body/mt:retrieveResponse/mt:result/mt:stater'   )r   
isinstancebool	TypeErrordictri   rk   r   r   r   rb   r_   rc   r   r   r   r   r   )r&   r   r:   r   r   r   metadata_typemembersmemberr   r   rc   r   async_process_id_r   r'   r'   r(   r     sZ   


	zSfdcMetadataApi.retrieveinclude_zipc                 K   s   | dd}|| j||d}tjdi |}ddd}t| jd | d| j| j||d	}t	|j
}	|	d
| j}
|
du rEtd|j
 |
S )z- Retrieves status for specified retrieval id r   r   )r   rh   r   
includeZipr   checkRetrieveStatusr   r   r   r   z5soapenv:Body/mt:checkRetrieveStatusResponse/mt:resultNr   r'   )r   ri   r   r   r   rb   r_   rc   r   r   r   r   r   r4   )r&   r   r   r:   r   r   r   rc   r   r   r6   r'   r'   r(   retrieve_retrieve_result6  s2   z(SfdcMetadataApi.retrieve_retrieve_resultc              	   K   s   | j |dfi |}|dd| jpd}|dd| j}g }|d| j}|D ]}||dd| jp4d|dd| jp=dd q'|d	d| jpKd}	t|	}
||||
fS )
z Retrieves ZIP file r   r   Nmt:errorMessagemt:details/mt:messagesr   r   r   r3   z
mt:zipFile)r   r   r   r   r   r   )r&   r   r:   r6   r   error_messagemessagesmessage_listr3   zipfile_base64r}   r'   r'   r(   retrieve_zipX  s:   
zSfdcMetadataApi.retrieve_zipc           	   	   K   s   | j |dfi |}|dd| jpd}|dd| j}g }|d| j}|D ]}||dd| jp4d|dd| jp=dd q'|||fS )	z$ Checks whether retrieval succeeded falser   Nr   r   r   r   r   )r   r   r   r   r   )	r&   r   r:   r6   r   r   r   r   r3   r'   r'   r(   check_retrieve_statusx  s.   

z%SfdcMetadataApi.check_retrieve_status)&rV   rW   rX   rY   _METADATA_API_BASE_URIr   requestsSessionrZ   r   r   r)   r   rw   r   ry   r	   r|   r   r   bytesr   r   r   r[   r   r   r   r   r   r
   r   r   r   r   r   r   r   r'   r'   r'   r(   r\      s    
	
M 
*
W
9
""
 $r\   )(rY   base64r   r   pathlibr   typingr   r   r   r	   r
   r   r   r   	xml.etreer   r   xml.etree.ElementTreer   r   
zeep.proxyr   zeep.xsdr   r   r   utilr   r   r   r   r   r   r   zeepr   r   r   r\   r'   r'   r'   r(   <module>   s    ( 2