U
    Hd7                     @   s,  d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ eG dd deZdd Zdd ZdZ eG dd deZ!dS )    N)datetime)	timedelta)SpooledTemporaryFile)ResourceNotFoundError)
BlobClient)BlobSasPermissions)BlobServiceClient)ContentSettings)generate_blob_sas)SuspiciousOperation)File)timezone)deconstructible)BaseStorage)
clean_name)get_available_overwrite_name)	safe_joinsetting)to_bytesc                       sR   e Zd Zdd Zdd Zdd ZeeeZ fddZ fd	d
Z	dd Z
  ZS )AzureStorageFilec                 C   s.   || _ || _|| _d| _d | _||| _d S )NF)name_mode_storage	_is_dirty_file_get_valid_path_path)selfr   modeZstorage r    C/tmp/pip-unpacked-wheel-1m3lyvgh/storages/backends/azure_storage.py__init__   s    zAzureStorageFile.__init__c                 C   s~   | j d k	r| j S t| jjdtdd d}d| jks<d| jkr^| jjj| j| jj	d}|
| d| jkrr|d || _ | j S )Nz.AzureStorageFileZFILE_UPLOAD_TEMP_DIR)max_sizesuffixdirratimeoutr   )r   r   r   max_memory_sizer   r   clientZdownload_blobr   r)   readintoseek)r   fileZdownload_streamr    r    r!   	_get_file$   s"    
 


zAzureStorageFile._get_filec                 C   s
   || _ d S N)r   )r   valuer    r    r!   	_set_file7   s    zAzureStorageFile._set_filec                    s*   d| j krd| j krtdt j||S )Nr&   r'   z!File was not opened in read mode.)r   AttributeErrorsuperread)r   argskwargs	__class__r    r!   r5   <   s    zAzureStorageFile.readc                    s<   d| j kr&d| j kr&d| j kr&tdd| _t t|S )Nw+r'   z"File was not opened in write mode.T)r   r3   r   r4   writer   )r   contentr8   r    r!   r<   A   s    
zAzureStorageFile.writec                 C   sL   | j d krd S | jr8| j d | j| j| j  d| _| j   d | _ d S )Nr   F)r   r   r-   r   _saver   closer   r    r    r!   r?   I   s    

zAzureStorageFile.close)__name__
__module____qualname__r"   r/   r2   propertyr.   r5   r<   r?   __classcell__r    r    r8   r!   r      s   
r   c                 C   sB   z
| j jW S  tk
r   Y nX z| jW S  tk
r<   Y nX d S r0   )r.   content_typer3   )r=   r    r    r!   _content_typeT   s    
rG   c                 C   sL   |  d} t| tkr"tdt t| s2td| ddkrHtd| S )Nz./zFile name max len is %dz7File name must contain one or more printable characters/   z0File name must not contain more than 256 slashes)striplen_AZURE_NAME_MAX_LEN
ValueErrorcount)sr    r    r!   r   `   s    
r   i   c                       s
  e Zd Z fddZdd Zdd Zedd Zed	d
 Zedd Z	edd Z
dd Zedd Zdd Zdd Zd8ddZef fdd	Zdd Zdd Zd d! Zd"d# Zd$d% Zd9d'd(Zd:d)d*Zd+d, Zd-d. Zd/d0 Zd;d2d3Zd<d4d5Zd6d7 Z  ZS )=AzureStoragec                    s:   t  jf | d | _d | _d | _d | _d | _t | _	d S r0   )
r4   r"   _service_client_custom_service_client_client_custom_client_user_delegation_keyr   utcnow_user_delegation_key_expiry)r   settingsr8   r    r!   r"   {   s    zAzureStorage.__init__c                 C   s   t dt dt di t dt ddt ddt d	d
t ddt dt ddt dddt dt dt ddt dt dt dt dd dS )NZAZURE_ACCOUNT_NAMEZAZURE_ACCOUNT_KEYZAZURE_OBJECT_PARAMETERSZAZURE_CONTAINERZ	AZURE_SSLTZAZURE_UPLOAD_MAX_CONN   ZAZURE_CONNECTION_TIMEOUT_SECS   ZAZURE_BLOB_MAX_MEMORY_SIZEi    ZAZURE_URL_EXPIRATION_SECSZAZURE_OVERWRITE_FILESFZAZURE_LOCATION zapplication/octet-streamZAZURE_CACHE_CONTROLZAZURE_SAS_TOKENZAZURE_ENDPOINT_SUFFIXzcore.windows.netZAZURE_CUSTOM_DOMAINZAZURE_CONNECTION_STRINGZAZURE_TOKEN_CREDENTIALZAZURE_API_VERSION)account_nameaccount_keyobject_parametersazure_container	azure_sslupload_max_connr)   r*   expiration_secsoverwrite_fileslocationdefault_content_typecache_control	sas_tokenendpoint_suffixcustom_domainconnection_stringtoken_credentialapi_versionr   r@   r    r    r!   get_default_settings   s(    z!AzureStorage.get_default_settingsc                 C   s   | j d k	rt| j S | jr&|r&| jnd| j| j}d| j|}d }| jr^| j| jd}n| j	rl| j	}n| j
rx| j
}i }| jr| j|d< t|fd|i|S )Nz
{}.blob.{}z{}://{})r\   r]   rl   
credential)rj   r   Zfrom_connection_stringri   formatr\   rh   azure_protocolr]   rg   rk   rl   )r   use_custom_domainZaccount_domainZaccount_urlrn   optionsr    r    r!   _get_service_client   s(    

z AzureStorage._get_service_clientc                 C   s   | j d kr| jdd| _ | j S )NFrq   )rQ   rs   r@   r    r    r!   service_client   s    
zAzureStorage.service_clientc                 C   s   | j d kr| jdd| _ | j S )NTrt   )rR   rs   r@   r    r    r!   custom_service_client   s    
z"AzureStorage.custom_service_clientc                 C   s    | j d kr| j| j| _ | j S r0   )rS   ru   get_container_clientr_   r@   r    r    r!   r+      s
    
zAzureStorage.clientc                 C   s    | j d kr| j| j| _ | j S r0   )rT   rv   rw   r_   r@   r    r    r!   custom_client   s
    
zAzureStorage.custom_clientc                 C   sV   | j d krd S | jd ks"|| jkrPt }|tdd }| jj||d| _|| _| jS )N   )days)Zkey_start_timekey_expiry_time)rk   rU   rW   r   rV   r   rv   get_user_delegation_key)r   expirynowr{   r    r    r!   r|      s    
 z$AzureStorage.get_user_delegation_keyc                 C   s   | j r
dS dS d S )Nhttpshttp)r`   r@   r    r    r!   rp      s    zAzureStorage.azure_protocolc                 C   s4   zt | j|W S  tk
r.   td| Y nX d S )Nz Attempted access to '%s' denied.)r   rd   rM   r   r   r   r    r    r!   _normalize_name   s    zAzureStorage._normalize_namec                 C   s   t | t|S r0   )r   r   r   r   r    r    r!   r      s
    zAzureStorage._get_valid_pathrbc                 C   s   t ||| S r0   )r   )r   r   r   r    r    r!   _open   s    zAzureStorage._openc                    s&   t |}| jrt||S t ||S )z
        Returns a filename that's free on the target storage system, and
        available for new content to be written to.
        )r   rc   r   r4   get_available_name)r   r   
max_lengthr8   r    r!   r      s    
zAzureStorage.get_available_namec                 C   s   | j | |}| S r0   )r+   get_blob_clientr   exists)r   r   blob_clientr    r    r!   r     s    zAzureStorage.existsc                 C   s6   z| j j| || jd W n tk
r0   Y nX d S Nr(   )r+   Zdelete_blobr   r)   r   r   r    r    r!   delete	  s    
zAzureStorage.deletec                 C   s&   | j | |}|j| jd}|jS r   )r+   r   r   get_blob_propertiesr)   size)r   r   r   
propertiesr    r    r!   r     s    zAzureStorage.sizec                 C   s`   t |}| |}| ||}t|tr.|j}|d | jj||t	f || j
| j| jd |S )Nr   )Zcontent_settingsZmax_concurrencyr)   	overwrite)r   r    _get_content_settings_parameters
isinstancer   r.   r-   r+   Zupload_blobr	   ra   r)   rc   )r   r   r=   Zcleaned_nameparamsr    r    r!   r>     s    


zAzureStorage._savec                 C   s   t  t|d S )N)seconds)r   rV   r   )r   expirer    r    r!   
_expire_at)  s    zAzureStorage._expire_atNc           
      C   s   |  |}|pi }|d kr | j}d }|rj| |}| |}t| j| j|f| j|tdd|d|}|}| j	
|j}	tj|	|djS )NT)r5   )r]   user_delegation_keyZ
permissionr}   )rn   )r   rb   r   r|   r
   r\   r_   r]   r   rx   r   urlr   Zfrom_blob_url)
r   r   r   
parametersr   rn   r}   r   rg   Zcontainer_blob_urlr    r    r!   r   -  s.    



zAzureStorage.urlc                 C   sR   i }t |\}}t|p"|p"| j}| j|d< ||d< ||d< || | |S )Nrf   rF   content_encoding)	mimetypes
guess_typerG   re   rf   updateget_object_parameters)r   r   r=   r   Zguessed_typer   rF   r    r    r!   r   G  s    
z-AzureStorage._get_content_settings_parametersc                 C   s
   | j  S )z
        Returns a dictionary that is passed to content settings. Override this
        method to adjust this on a per-object basis to set e.g ContentDisposition.

        By default, returns the value of AZURE_OBJECT_PARAMETERS.
        )r^   copyr   r    r    r!   r   W  s    z"AzureStorage.get_object_parametersc                 C   sd   | j | |}|j| jd}tdds6t|jS t	 }t
|jrXt|j|S |j|S )z
        Returns an (aware) datetime object containing the last modified time if
        USE_TZ is True, otherwise returns a naive datetime in the local timezone.
        r(   ZUSE_TZF)r+   r   r   r   r)   r   r   
make_naiveZlast_modifiedZget_current_timezoneis_naiveZ
make_aware
astimezone)r   r   r   r   tzr    r    r!   get_modified_time`  s    
zAzureStorage.get_modified_timec                 C   s"   |  |}t|r|S t|S )zBReturns a naive datetime object containing the last modified time.)r   r   r   r   )r   r   mtimer    r    r!   modified_timer  s    

zAzureStorage.modified_timer[   c                 C   s@   |r|  |}|r$|ds$|d7 }dd | jj|| jdD S )z!Return all files for a given pathrH   c                 S   s   g | ]
}|j qS r    )r   ).0Zblobr    r    r!   
<listcomp>  s   z)AzureStorage.list_all.<locals>.<listcomp>)Zname_starts_withr)   )r   endswithr+   Z
list_blobsr)   )r   pathr    r    r!   list_ally  s    
zAzureStorage.list_allc                 C   s`   g }t  }| |D ]>}|t|d }d|krH||ddd  q|| qt||fS )z
        Return directories and files for a given path.
        Leave the path empty to list the root.
        Order of dirs and files is undefined.
        NrH      r   )setr   rK   addsplitappendlist)r   r   filesdirsr   nr    r    r!   listdir  s    zAzureStorage.listdirc                 C   s0   t t| d td }| js,|td8 }|S )NZfooZ_1234567)rL   rK   r   rc   )r   max_lenr    r    r!   get_name_max_len  s    zAzureStorage.get_name_max_len)r   )NN)N)r[   )r[   ) rA   rB   rC   r"   rm   rs   rD   ru   rv   r+   rx   r|   rp   r   r   r   rL   r   r   r   r   r>   r   r   r   r   r   r   r   r   r   rE   r    r    r8   r!   rP   y   s>   	








	

rP   )"r   r   r   tempfiler   Zazure.core.exceptionsr   Zazure.storage.blobr   r   r   r	   r
   Zdjango.core.exceptionsr   Zdjango.core.files.baser   Zdjango.utilsr   Zdjango.utils.deconstructr   Zstorages.baser   Zstorages.utilsr   r   r   r   r   r   rG   r   rL   rP   r    r    r    r!   <module>   s4   :