o
    eM                     @   s  d Z ddlmZ ddlmZ ddlmZmZ ddlmZm	Z	m
Z
 ddlm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zddlmZ W n eyY   ddlmZ Y nw dd	lmZ ddlZdd
lmZ ddlZdgZdZdKddZdLddZdd Z dd Z!dd Z"dd Z#dd Z$dd Z%e% Z&dMd d!Z'd"d# Z(d$d% Z)d&d' Z*e+d(Z,e+d)Z-e+d*Z.d+d, Z/d-d. Z0d/d0 Z1G d1d2 d2e2Z3d3d4 Z4d5d6 Z5d7d8 Z6	 d9d: Z7d;d< Z8d=d> Z9d?d@ Z:dAdB Z;dCdD Z<dNdEdFZ=dZ>G dGdH dHe2Z?dIdJ Z@dS )Oz0
This module provide some tools for bce client.
    )print_function)absolute_import)strbytes)	iteritemsiterkeys
itervalues)compatN)urlparse)AES)http_headerss   .cdn.bcebos.coms   http    c                 C   s   |   }|r| | t }	 |}||  krdkr n n|}| |}|s(n|| |dkr7|t|8 }|dkr<nq| | t|	 S )a  
    Get MD5 from file by fp.

    :type fp: FileIO
    :param fp: None

    :type offset: long
    :param offset: None

    :type length: long
    :param length: None
    =======================
    :return:
        **file_size, MD(encode by base64)**
    Tr   )
tellseekhashlibmd5readupdatelenbase64standard_b64encodedigest)fpoffsetlengthZbuf_sizeZorigin_offsetr   bytes_to_readbuf r   >D:\Projects\ConvertPro\env\Lib\site-packages\baidubce/utils.pyget_md5_from_fp+   s&   



r    c                 C   s@   | dkr
t j  }nt j | }d|j|j|j|j|j|jf S )z
    Get cannonical time.

    :type timestamp: int
    :param timestamp: None
    =======================
    :return:
        **string of canonical_time**
    r   s   %04d-%02d-%02dT%02d:%02d:%02dZ)	datetimeutcnowutcfromtimestampyearmonthdayhourminutesecond)	timestampZutctimer   r   r   get_canonical_timeP   s   
r+   c                 C   sz   z6|  d}|d } | dkrW dS |  d}t|dkrW dS |D ]}t|dk s/t|dkr3 W dS q!W dS    Y dS )	z
    Check a string whether is a legal ip address.

    :type s: string
    :param s: None
    =======================
    :return:
        **Boolean**
       :r   s	   localhostT   .   F   )splitr   int)sZtmp_listir   r   r   is_ipc   s    


r4   c                 C   s
   t | S )z
    Encode a string to utf-8.

    :type input_string: string
    :param input_string: None
    =======================
    :return:
        **string**
    )r	   convert_to_bytes)Zinput_stringr   r   r   convert_to_standard_string~   s   
r6   c                 C   sF   i }| D ]\}}t |tr|d}t |tr|d}|||< q|S )z
    Transfer a header list to dict

    :type s: list
    :param s: None
    =======================
    :return:
        **dict**
       ")
isinstancer   strip)Zheader_listZ
header_mapabr   r   r   convert_header2map   s   





r<   c                 C   s6   t |D ]\}}|  |   kr|  S qdS )z
    Get element from dict which the lower of key and name are equal.

    :type name: string
    :param name: None

    :type container: dict
    :param container: None
    =======================
    :return:
        **Value**
     )r   r9   lower)name	containerkvr   r   r   safe_get_element   s
   rC   c                 C   s6   d}z| j dks| j dkrd}W |S W |S    Y |S )z
    Check whether the response is redirect.

    :type res: HttpResponse
    :param res: None

    :return:
        **Boolean**
    Fi-  i.  T)status)resis_redirectr   r   r   check_redirect   s   
rG   c                  C   sT   dd t dD } tjtj d D ]}|| t|< qt| d tr(dd | D } | S )z,"
    :return:
        **ASCII string**
    c                 S   s   g | ]}d | qS )z%%%02Xr   ).0r3   r   r   r   
<listcomp>   s    z-_get_normalized_char_list.<locals>.<listcomp>   z.~-_r   c                 S   s   g | ]}| d qS )utf-8)encode)rH   r2   r   r   r   rI      s    )rangestringascii_lettersdigitsordr8   r   )retchr   r   r   _get_normalized_char_list   s   rT   Tc                 C   st   g }t | D ].}d}d}t|trt|d}|}n|}t|}|dkr-|s-|d q|t|  qd|S )a  
    Encode in_str.
    When encoding_slash is True, don't encode skip_chars, vice versa.

    :type in_str: string
    :param in_str: None

    :type encoding_slash: Bool
    :param encoding_slash: None
    ===============================
    :return:
        **ASCII  string**
    r=   r   rK      /    )	r6   r8   r1   chrrL   rQ   append_NORMALIZED_CHAR_LISTjoin)Zin_strZencoding_slashtmprS   sepindexr   r   r   normalize_string   s   

r^   c                 G   s   | g}|D ]}|r| t|d qt|dkr?|d d|d< |d d|d< tdt|d D ]}|| d||< q3d|S )z
    Append path_components to the end of base_uri in order, and ignore all empty strings and None

    :param base_uri: None
    :type base_uri: string

    :param path_components: None

    :return: the final url
    :rtype: str
    F   r   rU   r   )rX   r^   r   rstriplstriprM   r9   rZ   )Zbase_uriZpath_componentsr[   pathr3   r   r   r   
append_uri   s   
rc   c                 C   s   d}t | dk st | dkrdS | d dks| d dkrdS d| d	   kr*d
ks;n d| d	   kr8dks;dS  dS | D ]	}||vrF dS q=dS )z
    Check bucket name whether is legal.

    :type bucket: string
    :param bucket: None
    =======================
    :return:
        **Boolean**
    z%abcdefghijklmnopqrstuvwxyz0123456789-   ?   Fr   -_r:   r   z09T)r   )Zbucketalphabetr3   r   r   r   check_bucket_valid  s   
0rl   c                 C   s   t  }d|d< d|d< d|d< d|d< d	|d
< d|d< d|d< d|d< d|d< d|d< d|d< z2t| } tj|  }|dd }|t|v rO|| }nddl	}|
  |jd| d}W n   d}Y |sld}t|S )z
    Get file type by filename.

    :type file_name: string
    :param file_name: None
    =======================
    :return:
        **Type Value**
    zapplication/javascriptjszAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetZxlsxzDapplication/vnd.openxmlformats-officedocument.spreadsheetml.templateZxltxzEapplication/vnd.openxmlformats-officedocument.presentationml.templateZpotxzFapplication/vnd.openxmlformats-officedocument.presentationml.slideshowZppsxzIapplication/vnd.openxmlformats-officedocument.presentationml.presentationZpptxzBapplication/vnd.openxmlformats-officedocument.presentationml.slideZsldxzGapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentZdocxzGapplication/vnd.openxmlformats-officedocument.wordprocessingml.templateZdotxz.application/vnd.ms-excel.addin.macroEnabled.12Zxlamz5application/vnd.ms-excel.sheet.binary.macroEnabled.12Zxlsb.r   r   Nzapplication/octet-stream)dictr	   convert_to_stringosrb   basenamer>   r0   r   	mimetypesinit	types_mapgetr5   )	file_nameZmime_mapr?   suffixZ	mime_typers   r   r   r   guess_content_type_by_file_name(  s6   



ry   z(.)([A-Z][a-z]+)z([a-z])([0-9]{2,})z([a-z0-9])([A-Z])c                 C   s4   | dkrdS t d| }td|}td| S )a  Convert camel case to a "pythonic" name.
    Examples::
        pythonize_name('CamelCase') -> 'camel_case'
        pythonize_name('already_pythonized') -> 'already_pythonized'
        pythonize_name('HTTPRequest') -> 'http_request'
        pythonize_name('HTTPStatus200Ok') -> 'http_status_200_ok'
        pythonize_name('UPPER') -> 'upper'
        pythonize_name('ContentMd5')->'content_md5'
        pythonize_name('') -> ''
    ZeTagetagz\1_\2)_first_cap_regexsub_number_cap_regex_end_cap_regexr>   )r?   s1s2r   r   r   pythonize_nameV  s
   r   c                 C   sn   | du rdS g }t | D ]!\}}|r|jtj kr-|du r d}|dt|t|f  q|  d|S )z@

    :param params:
    :param for_signature:
    :return:
    Nr=   s   %s=%s   &)r   r>   r   ZAUTHORIZATIONrX   r^   sortrZ   )paramsZfor_signatureresultrA   rB   r   r   r   get_canonical_querystringh  s   
r   c                 C   s   g }t | jD ]4\}}|ds;|dkr;t|tr#|d||f  qt|tr2|d||f  q|d||f  qdd| S )z#

    :param obj:
    :return:
    __raw_dataz%s:'%s'z%s:u'%s'z%s:%sz{%s},)r   __dict__
startswithr8   r   rX   r   rZ   )objr[   rA   rB   r   r   r   print_object{  s   

r   c                   @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
Expandoz
    Expandable class
    Nc                 C   s   |r
| j | d S d S N)r   r   )self	attr_dictr   r   r   __init__  s   zExpando.__init__c                 C   s   | drtd S )Nr   )r   AttributeError)r   itemr   r   r   __getattr__  s   
zExpando.__getattr__c                 C   s   t | S r   )r   r   r   r   r   __repr__  s   zExpando.__repr__r   )__name__
__module____qualname____doc__r   r   r   r   r   r   r   r     s
    
r   c                 C   sD   i }t | D ]\}}t|tjst|}t|}|||< qt|S )z!

    :param d:
    :return:
    )r   r8   r	   string_typesrp   r   r   )dattrrA   rB   r   r   r   dict_to_python_object  s   

r   c                     s    fdd}|S )zG
    decorator of input param check
    :param types:
    :return:
    c                    s    fdd} j |_ |S )Nc                     s   t | D ]8\}} jj| v r<|d u rtd jj|  t| jj|  s<td jj| | jj|  f qt|D ]$\}}|v re|d u rStd| t|| setd||| f qA | i |S )Nzarg "%s" should not be Nonezarg "%s"= %r does not match %s)	enumerate__code__co_varnames
ValueErrorr8   	TypeErrorr   )argskwdsr3   rB   rA   )ftypesr   r   
_decorated  s,   

z/required.<locals>._required.<locals>._decorated)r   )r   r   r   )r   r   	_required  s   zrequired.<locals>._requiredr   )r   r   r   r   r   required  s   r   c              
   C   s   d| vrd|  } zt | t|j}W n ty* } ztd| t|f d}~ww |jttj	j
jkr@tj	j
}tj	j
j}n|jttj	jjkrUtj	j}tj	jj}ntd|j |j}|jdurg|j}|||fS )ac  
    parse protocol, host, port from endpoint in config

    :type: string
    :param endpoint: endpoint in config

    :type: baidubce.protocol.HTTP or baidubce.protocol.HTTPS
    :param default_protocol: if there is no scheme in endpoint,
                              we will use this protocol as default
    :return: tuple of protocol, host, port
       //zInvalid endpoint:%s, error:%sNzUnsupported protocol %s)r
   r	   r5   r?   	Exceptionr   rp   schemebaidubceprotocolHTTPdefault_portZHTTPShostnameport)ZendpointZdefault_protocolZparse_resulter   r   hostr   r   r   parse_host_port  s0   


r   c                 C   s`   dd }|dd }t j}t ||}|| }|jdd}||}t|d}	|	jdd}
|
S )zc

    :param adminpass: adminpass
    :param secretkey: secretkey
    :return: cipheradminpass
    c                 S   s(   | dt | d  tdt | d    S )N   )r   rW   )r2   r   r   r   <lambda>
  s   ( z+aes128_encrypt_16char_key.<locals>.<lambda>r   r   rK   )encoding	hex_codec)r   ZMODE_ECBnewrL   Zencryptcodecsdecode)Z	adminpassZ	secretkeyZpad_itkeymodeZcryptorZ	pad_adminZbyte_pad_adminZcryptoradminpassZbyte_cipheradminpassZcipheradminpassr   r   r   aes128_encrypt_16char_key   s   

r   c                 C   s.   | du rdS t D ]}|  |r dS qdS )zU
    :param host: custom domain
    :return: domain end with cdn endpoint or not
    NFT)DEFAULT_CNAME_LIKE_LISTr>   endswith)r   rx   r   r   r   is_cname_like_host  s   r   c                 C   sp   | du s|du r
dS |   tr,| d}t|dkr*|d   t|  S dS |   t|  S )zQ
    custom host : xxx.region.bcebos.com
    : return: custom, domain or not
    NFr      r_   )r>   r   HTTP_PROTOCOL_HEADr0   r   r	   r5   )r   Zbucket_nameZ
host_splitr   r   r   is_custom_host*  s   
r   c                 C   sB   t | dr	t| S t | dr| jS t | drt | drt| S d S )N__len__r   r   r   )hasattrr   file_object_remaining_bytes)datar   r   r   _get_data_size:  s   

r   c                 C   s4   |   }| dtj |   }| |tj || S Nr   )r   r   rq   SEEK_ENDSEEK_SET)fileobjcurrentendr   r   r   r   F  s
   r   c                 C   s   | r	| || d S d S r   r   )progress_callbackconsumed_bytestotal_bytesr   r   r   _invoke_progress_callbackO  s   r   c                 C   s6   |du rt | }|du rtd| jjt| ||S )aH  return a adapter,when reading 'data', that is, calling read or iterating 
    over it Call the progress callback function

    :param data: bytes,file object or iterable
    :param progress_callback: callback function, ref:`_default_progress_callback`
    :param size: size of `data`

    :return: callback function adapter
    Nz{0} is not a file object)r   r   format	__class__r   _BytesAndFileAdapter)r   r   sizer   r   r   make_progress_adapterS  s
   r   c                   @   s<   e Zd ZdZdddZedd Zdd ZeZdd	d
Z	dS )r   a.  With this adapter, you can add progress monitoring to 'data'.

    :param data: bytes or file object
    :param progress_callback: user-provided callback function. like callback(bytes_read, total_bytes)
        bytes_read is readed bytes;total_bytes is total bytes
    :param int size : data size 
    Nc                 C   s   || _ || _|| _d| _d S r   )r   r   r   r   )r   r   r   r   r   r   r   r   p  s   
z_BytesAndFileAdapter.__init__c                 C   s   | j S r   )r   r   r   r   r   r   v  s   z_BytesAndFileAdapter.lenc                 C   s   dS )NTr   r   r   r   r   __bool__{  s   z_BytesAndFileAdapter.__bool__c                 C   s   | j | jkrtdS |d u s|dk r| j| j  }n	t|| j| j  }t| jtr5| j| j | j |  }n| j|}|  j |7  _ t	| j
t| j | j| j |S )Nr=   r   )r   r   r	   r5   minr8   r   r   r   r   r   )r   amtr   contentr   r   r   r     s   
z_BytesAndFileAdapter.read)NNr   )
r   r   r   r   r   propertyr   r   __nonzero__r   r   r   r   r   r   h  s    

r   c                 C   sx   |r:t dt| t|  }d| }dd|  }|dkr(td|||dd ntd|||dd tj  dS dS )	zProgress bar callback function that calculates the percentage of current completion
    
    :param consumed_bytes: Amount of data that has been uploaded/downloaded
    :param total_bytes: According to the total amount
    d   *rn   z{}%[{}->{}]
r=   )r   z{}%[{}->{}]N)r1   floatprintr   sysstdoutflush)r   r   ZrateZstart_progressZend_progressr   r   r   default_progress_callback  s   r   )r   r   r   )r   )Tr   )Ar   
__future__r   r   builtinsr   r   Zfuture.utilsr   r   r   r   r	   rq   rer!   r   r   rN   r   urllib.parser
   ImportErrorZCrypto.Cipherr   Zbaidubce.httpr   r   r   r   r    r+   r4   r6   r<   rC   rG   rT   rY   r^   rc   rl   ry   compiler{   r}   r~   r   r   r   objectr   r   r   r   r   r   r   r   r   r   r   _CHUNK_SIZEr   r   r   r   r   r   <module>   st   

%
!
)

'	
;