B
    b8F                 @   s   d Z ddlmZ ddlmZ ddlmZ dZdZdZdZdd	l	Z	dd	l
Z
dd	lZdd	lZdd	lZdd	lZdd	lZydd	lZW n ek
r   dd	lZY nX dd
lmZ d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d	S )a  
ApiBase.py
^^^^^^^^^^

Core methods supporting the wwPDB OneDep webservice API.

:copyright: @wwPDB
:license: Apache 2.0, see LICENSE file for more details.


Updates:
     3-Aug-2016 jdw  add Authorization header
    20-Sep-2016 jdw  refactor for standard packaging
    21-Sep-2016 jdw  add download by name and type.
    21-Sep-2016 jdw  make parameters optional in all prototypes
    25-Sep-2016 jdw  revise exception handling
    )print_function)unicode_literals)divisionzrestructuredtext enzJohn Westbrookzjwest@rcsb.rutgers.eduz
Apache 2.0N)__version__)InsecureRequestWarningc               @   s   e Zd Zd0ddZdd Zdd Zd	d
 Zd1ddZdd Zdd Z	dd Z
dd Zdd Zd2ddZd3ddZd4ddZd5d d!Zd6d#d$Zd7d%d&Zd'd( Zd)d* Zd8d,d-Zd.d/ ZdS )9ApiBaseNTc             C   s   t d d| _|r|nd| _|r&|nd| _|r4|nd| _t | _|rL|ndt	t
j d f | jjd< d	d
| jf | jjd< d| _d| _d| _|| _i | _|stjjt dS )a  
        Core methods supporting the OneDep web client API.

        :param string apiKey: (Optional) security token.
        :param string userAgent: (Optional) alternative identifier for calling application.
        :param string apiName: (Optional) API service name
        :param string apiUrl: (Optional) API service base URL.
        :param string verify:  (Optional) verify SSL certificate

        zService initializingi   zhttps://localhostZ	anonymousonedepzOneDepApiClient/%s Python/%s r   z
User-Agentz%s %sZBearerzwwpdb-api-tokenZonedep_error_flagZonedep_status_textN)logdebug_ApiBase__chunkSize_apiUrlZ_apiKey_apiNamerequestssession_ApiBase__myreqr   sysversionsplitheaders_returnApiErrorFlagKey_returnApiStatusTextKey
_sessionId_verify_reservedContentTypesZpackagesZurllib3Zdisable_warningsr   )selfZapiKeyZ	userAgentZapiNameapiUrlverify r   3lib/python3.7/site-packages/onedep/utils/ApiBase.py__init__5   s    

&zApiBase.__init__c             C   s"   i }| j d|}|dd| _|S )zCreate and maintain a session context in all subsequent API requests.

        :rtype: json service response converted to dictionary (with mininal keys: api_error_flag, api_status_text, session_id)
        r   
session_idN)r   )postgetr   )r   pDrDr   r   r   createSessionU   s    zApiBase.createSessionc             C   s
   || _ dS )z3Set the identifier for the current session context.N)r   )r   Z	sessionIdr   r   r   
setSession`   s    zApiBase.setSessionc             C   s   | j S )N)r   )r   r   r   r   
getSessiond   s    zApiBase.getSessionFc             C   s*   | j s|r|   d|kr&|  |d< dS )zUInternal method to add the current session context to the input parameter dictionary.r    N)r   r%   r'   )r   r#   autor   r   r   Z__addSessionContextg   s    
zApiBase.__addSessionContextc             C   s   || _ || _d S )N)r   r   )r   ZerrorFlagKeyZstatusTextKeyr   r   r   setApiReturnStatusKeyso   s    zApiBase.setApiReturnStatusKeysc             C   s    yt || _dS    dS d S )NTF)copydeepcopyr   )r   ZcontentTypeDictr   r   r   setContentTypess   s
    zApiBase.setContentTypesc             C   s   y
| j  S    g S d S )N)r   keys)r   r   r   r   getContentTypesz   s    
zApiBase.getContentTypesc             C   s   || j kr| j | S g S d S )N)r   )r   contentTyper   r   r   getContentFormatList   s    

zApiBase.getContentFormatListc             C   s0   y || j kr| j | d S d S W n
   d S d S )Nr   )r   )r   r/   r   r   r   getContentFormatDefault   s    
zApiBase.getContentFormatDefaultdownloadc             K   s6   i }x|D ]}|| ||< q
W ||d< | j ||f|S )a  Construct GET request to download the target fileName to dstPath.

        :param string fileName: file name target for download
        :param string dstPath: full local path to file for download
        :param string endPoint:  API endPoint  - valws.
        :param params: (Optional) Parameters as keyword arguments.

        :rtype: json response converted to dictionary

        filename)_ApiBase__download)r   dstPathZfileNameendPointparams_paramspr   r   r   downloadByName   s
    
zApiBase.downloadByNamec             K   sp   i }|| j kr&d|| j< d|| j< |S i }x|D ]}|| ||< q0W ||d< | ||d< | j|fd|i|S )a  Construct GET request to download the target data object type to dstPath.

        :param string contentType: data object content type target download
        :param string dstPath: full local path to file for download
        :param string endPoint:  API endPoint  - valws.
        :param params: (Optional) Parameters as keyword arguments.

        :rtype: json response converted to dictionary

        TzUnrecognized file typeZcontenttypeZ
formattyper6   )r   r   r   r1   r4   )r   r5   r/   r6   r7   r$   r8   r9   r   r   r   downloadByType   s    



zApiBase.downloadByTypec          
   K   s  i }x|D ]}|| ||< q
W |  | td|| i }d|| j< d|| j< | j| j| j|f|}td| y| jj	||| j
dd}|jdkrt|d&}	x|| jD ]}
|	|
 qW W dQ R X d	|| j< d
|| j< td|jj td|j W n. tk
r* } z| j|ddS d}~X Y nX | |\}}|rD|S yB| |}|jd }||krzd|| j< d|| j< n
td W n$   d|| j< d| || j< Y nX |S )a  Internal method to construct GET request to download the target fileName or content type to dstPath.

        :param string dstPath: full path to file for download
        :param string endPoint:  API endPoint  - valws.
        :param params: Parameters as keyword arguments including file name/type specification and session details.

        :rtype: json response converted to dictionary

        z DOWNLOAD BEGINS for : %s %rTzMiscellaneous api failurezRequest: URL: %r)datar   stream   wbNFokzdownload request headers %rzdownload response headers %rz%Download request processing exception)
msgDefaultchecksum_md5zChecksum failurezchecksum comparison successz&Download checksum processing error %r )_ApiBase__addSessionContextr	   r
   r   r   _ApiBase__encodeUrlr   r   r   r"   r   status_codeopenZiter_contentr   writerequestr   	Exception_ApiBase__filterExceptions_ApiBase__filterErrorsgetMD5)r   r5   r6   r7   r8   r9   r$   urlresponsefchunkeerrFlagerrDZmyDigestZ	theDigestr   r   r   Z
__download   sH    












zApiBase.__downloaduploadc          
   K   s2  t d||| i }d|| j< d|| j< || jkrJd|| j< d|| j< |S || j| krpd|| j< d|| j< |S t d| i }x|D ]}|| ||< qW t d| | | t d| yL| |}	|	|d	< tj	|\}
}t
|d
}d||fi}||d< ||d< W n   d|| j< d|| j< |S d| j| j|f }t d|| y*| jj|||| jd}t d|jj W n. tk
r } z| j|ddS d}~X Y nX | |\}}|r|S y2|t|j |d || j< |d || j< W n@ tk
r, } z d|| j< dt| || j< W dd}~X Y nX |S )a  Construct POST request to perform multipart/ file upload and return the JSON response.

        :param string filepath: full path to file for upload
        :param string contentType: type ['model', 'structure-factors', 'nmr-chemical-shifts', 'nmr-restraints', 'em-volume']
        :param string fileFormat:  (pdbx)
        :param string endPoint:  API endPoint  - valws.
        :param params: (Optional) Parameters as keyword arguments.

        :rtype: json response converted to dictionary


        >>> url = 'http://httpbin.org/post'
        >>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
        >>> r = requests.post(url, files=files)

        zupload request: %s %s %sTzMiscellaneous api failurezUnrecognized file typezUnrecognized file formatz A params %rz B _params %rz C _params %rrB   rbfileZcontent_typeZfile_formatz&Input file access or processing error z%s/service/%s/%szRequest: URL: %s PARAMS: %r)filesr<   r   zpost headers %rz#Upload request processing exception)rA   N	errorflagstatusmessagez#Upload response processing error %s)r	   r
   r   r   r   rC   rL   ospathr   rF   r   r   r   r!   r   rH   r   rI   rJ   rK   updatejsonloadstextstr)r   ZfilePathr/   Z
fileFormatr6   r7   r$   r8   r9   md5_fnZfobjZfDrM   rN   rQ   rR   rS   r   r   r   rT      sb    













$zApiBase.uploadOneDep API service failurec             C   s>   d}|}yt |}W n   Y nX i }||| j< ||| j< |S )zHandle typical exceptions and map these to response dictionary -

        :param exception: target exception object

        :rtype dictionary:  response dictionary (with mininal keys: api_error_flag, api_status_text)

        T)r`   r   r   )r   Z	exceptionrA   	errorFlagmsgr$   r   r   r   Z__filterExceptionsC  s    

zApiBase.__filterExceptionsc             C   sr   d}d}y<|j dkrBd}|}yt|j}|d }W n   Y nX W n   Y nX i }||| j< ||| j< ||fS )a(  Check the response packet for typical error various error types and map these to
        response dictionary -

        :param rsp request response object: target response object

        :rtype tuple:  errorFlag, response dictionary (with mininal keys: api_error_flag, api_status_text)

        FZunprocessed)i  i  TZ
statustext)rE   r]   r^   r_   r   r   )r   rN   rA   re   rf   rS   r$   r   r   r   Z__filterErrorsW  s"    	



zApiBase.__filterErrorsc          
   K   sD  i }d|| j < d|| j< d| j| j|f }i }x|D ]}|| ||< q4W | | td|| y(| jj||| j	d}td|j
j W n, tk
r } z| j|ddS d	}~X Y nX | |\}	}
|	r|
S y2|t|j |d
 || j < |d || j< W n@ tk
r> } z d|| j < dt| || j< W d	d	}~X Y nX |S )zConstruct POST request and return the JSON response.

        :param string endPoint:  API endPoint  - valws.
        :param params: (Optional) Parameters as keyword arguments.

        :rtype: json response converted to dictionary
        TzMiscellaneous api failurez%s/service/%s/%szRequest: %s %s)r<   r   zpost headers %rz!POST request processing exception)rA   NrX   rY   z!POST request processing error %r )r   r   r   r   rC   r	   r
   r   r!   r   rH   r   rI   rJ   rK   r\   r]   r^   r_   r`   )r   r6   r7   r$   rM   r8   r9   rN   rQ   rR   rS   r   r   r   r!   t  s2    




$zApiBase.postc          
   K   s8  i }d|| j < d|| j< i }x|D ]}|| ||< q"W | | | j| j| j|f|}y&| jj|| jd}t	
d|jj W n, tk
r } z| j|ddS d}~X Y nX | |\}	}
|	r|
S y2|t|j |d || j < |d	 || j< W n@ tk
r2 } z d|| j < d
t| || j< W dd}~X Y nX |S )zConstruct GET request and return the JSON response.

        :param string endPoint:  API endPoint  - valws.
        :param params: (Optional) Parameters as keyword arguments.

        :rtype: json response converted to dictionary
        TzMiscellaneous api failure)r   zget headers %rz GET request processing exception)rA   NrX   rY   z GET request processing error %r )r   r   rC   rD   r   r   r   r"   r   r	   r
   rH   r   rI   rJ   rK   r\   r]   r^   r_   r`   )r   r6   r7   r$   r8   r9   rM   rN   rQ   rR   rS   r   r   r   r"     s0    




$zApiBase.get   c          	      sZ   t  }t|d.x&t fdddD ]}|| q*W W dQ R X |rR| S | S )a  
        Chunked MD5 function -

        Block size directly depends on the block size of your filesystem
        to avoid performances issues

        Linux Ext4 block size
            sudo /sbin/blockdev --getbsz /dev/sda1
            > Block size:               4096

        rU   c                  s
     S )N)readr   )
block_sizerO   r   r   <lambda>      z ApiBase.getMD5.<locals>.<lambda>rk   N)hashlibra   rF   iterr\   Z	hexdigestZdigest)r   r[   ri   hrra   rP   r   )ri   rO   r   rL     s    zApiBase.getMD5c          	   K   sR   g }x6|  D ]*\}}|d|tjjjt|f  qW d|||d|f S )a  Internal method to construct API url for a GET request.

        :param string api: the api service name -
        :param string endPoint:  API endPoint  - valws.
        :param params: (Optional) Parameters as keyword arguments.

        :rtype: string
        z%s=%sz%s/service/%s/%s?%s&)	itemsappendsixZmovesZurllibparseZ
quote_plusr`   join)r   r   Zapir6   r7   Zqskvr   r   r   Z__encodeUrl  s    	&zApiBase.__encodeUrl)NNNNT)F)r2   )r2   )r2   )rT   )rd   )rd   )rg   T)__name__
__module____qualname__r   r%   r&   r'   rC   r)   r,   r.   r0   r1   r:   r;   r4   rT   rJ   rK   r!   r"   rL   rD   r   r   r   r   r   4   s(   
 
	


9
O

'%
r   c               @   s   e Zd ZdZdS )ApiExceptionzService general exception.N)rw   rx   ry   __doc__r   r   r   r   rz     s   rz   c               @   s   e Zd ZdZdS )ApiAuthExceptionz!Service authentication exception.N)rw   rx   ry   r{   r   r   r   r   r|     s   r|   )r{   Z
__future__r   r   r   Z__docformat__
__author__Z	__email__Z__license__Zloggingr   rZ   r*   rl   r   rr   r]   ImportErrorZ
simplejsonr   r   Z$requests.packages.urllib3.exceptionsr   Z	getLoggerrw   r	   objectr   rI   rz   r|   r   r   r   r   <module>   s6   
   3