U
    Hdh0                     @   sf  d dl Z d dlZd dlZ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 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$ W n e%k
r2   e	dY nX dZ&dZ'G dd deeZ(eG dd deZ)dS )    N)	timedelta)SpooledTemporaryFile)ImproperlyConfigured)SuspiciousOperation)File)timezone)deconstructible)BaseStorage)CompressedFileMixin)check_location)
clean_name)get_available_overwrite_name)	safe_join)setting)to_bytes)NotFound)Blob)Client)_quote)DEFAULT_RETRYzfCould not load Google Cloud Storage bindings.
See https://github.com/GoogleCloudPlatform/gcloud-pythoncontent_encodingcontent_typec                       s`   e Zd Zdd Zedd Zdd Zdd ZeeeZd fd
d	Z	 fddZ
dd Z  ZS )GoogleCloudFilec                 C   sj   || _ t|d | _|| _|| _|jj||jd| _	| j	sZd|krZt
| j |j|jd| _	d | _d| _d S )Nr   )
chunk_sizewF)name	mimetypes
guess_type	mime_type_mode_storagebucketget_blobblob_chunk_sizeblobr   _file	_is_dirty)selfr   modeZstorage r)   </tmp/pip-unpacked-wheel-1m3lyvgh/storages/backends/gcloud.py__init__'   s       zGoogleCloudFile.__init__c                 C   s   | j jS N)r$   sizer'   r)   r)   r*   r-   5   s    zGoogleCloudFile.sizec                 C   sz   | j d krtt| jjdtdd| _ d| jkrLd| _| j| j  | j 	d | jj
rt| jjdkrt| j| j| j d| _ | j S )	Nz.GSStorageFileZFILE_UPLOAD_TEMP_DIR)max_sizesuffixdirrFr   gzip)r(   file)r%   r   r    max_memory_sizer   r   r&   r$   Zdownload_to_fileseekr3   r   Z_decompress_filer.   r)   r)   r*   	_get_file9   s    

zGoogleCloudFile._get_filec                 C   s
   || _ d S r,   )r%   )r'   valuer)   r)   r*   	_set_fileH   s    zGoogleCloudFile._set_fileNc                    s*   d| j krtd|d krd}t |S )Nr2   z!File was not opened in read mode.)r   AttributeErrorsuperread)r'   	num_bytes	__class__r)   r*   r=   M   s
    
zGoogleCloudFile.readc                    s(   d| j krtdd| _t t|S )Nr   z"File was not opened in write mode.T)r   r;   r&   r<   writer   )r'   contentr?   r)   r*   rA   V   s    
zGoogleCloudFile.writec              	   C   sX   | j d k	rT| jrD| j| j}| jj| jd| jt	|
d| jjd | j   d | _ d S )NTacl)rewindr   retrypredefined_acl)r%   r&   r    get_object_parametersr   r$   upload_from_filer4   r   r   getdefault_aclclose)r'   blob_paramsr)   r)   r*   rK   \   s    
  
zGoogleCloudFile.close)N)__name__
__module____qualname__r+   propertyr-   r7   r9   r4   r=   rA   rK   __classcell__r)   r)   r?   r*   r   &   s   

	r   c                       s   e Zd Z fddZdd Ze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 Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd*d%d&Zd+ fd'd(	Z  ZS ),GoogleCloudStoragec                    s&   t  jf | t|  d | _d | _d S r,   )r<   r+   r   _bucket_client)r'   settingsr?   r)   r*   r+   j   s    zGoogleCloudStorage.__init__c                 C   sx   t dt dt dt dd t ddt dt dd	t d
tddt ddt ddt dd	t dt di t ddt ddS )NZGS_PROJECT_IDZGS_CREDENTIALSZGS_BUCKET_NAMEZGS_CUSTOM_ENDPOINTZGS_LOCATION ZGS_DEFAULT_ACLZGS_QUERYSTRING_AUTHTZGS_EXPIRATIONiQ )secondsZGS_IS_GZIPPEDFZGZIP_CONTENT_TYPES)ztext/cssztext/javascriptzapplication/javascriptzapplication/x-javascriptzimage/svg+xmlZGS_FILE_OVERWRITEZGS_CACHE_CONTROLZGS_OBJECT_PARAMETERSZGS_MAX_MEMORY_SIZEr   ZGS_BLOB_CHUNK_SIZE)
project_idcredentialsbucket_namecustom_endpointlocationrJ   querystring_auth
expirationr3   gzip_content_typesfile_overwritecache_controlobject_parametersr5   r#   )r   r   r.   r)   r)   r*   get_default_settingsr   s     z'GoogleCloudStorage.get_default_settingsc                 C   s"   | j d krt| j| jd| _ | j S )N)projectrY   )rT   r   rX   rY   r.   r)   r)   r*   client   s    
zGoogleCloudStorage.clientc                 C   s    | j d kr| j| j| _ | j S r,   )rS   re   r!   rZ   r.   r)   r)   r*   r!      s    
zGoogleCloudStorage.bucketc                 C   s4   zt | j|W S  tk
r.   td| Y nX dS )aA  
        Normalizes the name so that paths like /path/to/ignored/../something.txt
        and ./file.txt work.  Note that clean_name adds ./ to some paths so
        they need to be fixed here. We check to make sure that the path pointed
        to is not outside the directory specified by the LOCATION setting.
        z Attempted access to '%s' denied.N)r   r\   
ValueErrorr   r'   r   r)   r)   r*   _normalize_name   s    z"GoogleCloudStorage._normalize_namerbc                 C   s0   |  t|}t||| }|js,td| |S )NzFile does not exist: %s)rh   r   r   r$   FileNotFoundError)r'   r   r(   file_objectr)   r)   r*   _open   s
    zGoogleCloudStorage._openc              	   C   sN   | d t }tjd|dd}|t|  W 5 Q R X | d |S )Nr   wbg        )r(   fileobjmtime)r6   ioBytesIOr3   GzipFilerA   r   r=   )r'   rB   Zzbufzfiler)   r)   r*   _compress_content   s    

z$GoogleCloudStorage._compress_contentc           	      C   s   t |}| |}||_t|d| }i }| |}|d| j|d< |t|j|t< | j	r|t | j
krt|kr| |}d|t< | D ]\}}t|j|| q|jj|fdtt|dd d| |S )NrwrC   rF   r3   Tr-   )rD   rE   r-   )r   rh   r   r   rG   poprJ   CONTENT_TYPEr   r3   r_   CONTENT_ENCODINGrt   itemssetattrr$   rH   r   getattr)	r'   r   rB   Zcleaned_namerk   Zupload_paramsrL   propvalr)   r)   r*   _save   s6    



zGoogleCloudStorage._savec                 C   s2   | j  }d|kr.| jr.tdt | j|d< |S )zOverride this to return a dictionary of overwritable blob-property to value.

        Returns GS_OBJECT_PARAMETRS by default. See the docs for all possible options.
        ra   zThe GS_CACHE_CONTROL setting is deprecated. Use GS_OBJECT_PARAMETERS to set any writable blob property or override GoogleCloudStorage.get_object_parameters to vary the parameters per object.)rb   copyra   warningswarnDeprecationWarning)r'   r   rb   r)   r)   r*   rG      s    

z(GoogleCloudStorage.get_object_parametersc                 C   s<   |  t|}z| jj|td W n tk
r6   Y nX d S )N)rE   )rh   r   r!   Zdelete_blobr   r   rg   r)   r)   r*   delete   s
    zGoogleCloudStorage.deletec                 C   sN   |s0z| j | j W dS  tk
r.   Y dS X | t|}t| j|S )NTF)re   Z
get_bucketr!   r   rh   r   boolr"   rg   r)   r)   r*   exists   s    zGoogleCloudStorage.existsc           
      C   s   |  t|}|r$|ds$|d7 }| jj|dd}t|}|j}g }g }|D ]}|jd}|	|d  qN|D ]}	|	d}|	|d  qrt||fS )N/)prefix	delimiterr:   )
rh   r   endswithr!   Z
list_blobslistprefixesr   splitappend)
r'   r   iteratorZblobsr   filesdirsr$   partsZfolder_pathr)   r)   r*   listdir   s    
zGoogleCloudStorage.listdirc                 C   s&   | j |}|d kr"td||S )NzFile does not exist: {})r!   r"   r   formatr'   r   r$   r)   r)   r*   	_get_blob  s    zGoogleCloudStorage._get_blobc                 C   s   |  t|}| |}|jS r,   )rh   r   r   r-   r   r)   r)   r*   r-     s    
zGoogleCloudStorage.sizec                 C   s$   |  t|}| |}t|jS r,   )rh   r   r   r   
make_naiveupdatedr   r)   r)   r*   modified_time  s    
z GoogleCloudStorage.modified_timec                 C   s4   |  t|}| |}|j}tdr*|S t|S )NUSE_TZ)rh   r   r   r   r   r   r   )r'   r   r$   r   r)   r)   r*   get_modified_time$  s    
z$GoogleCloudStorage.get_modified_timec                 C   s4   |  t|}| |}|j}tdr*|S t|S )z
        Return the creation time (as a datetime) of the file specified by name.
        The datetime will be timezone-aware if USE_TZ=True.
        r   )rh   r   r   Ztime_createdr   r   r   )r'   r   r$   createdr)   r)   r*   get_created_time*  s    
z#GoogleCloudStorage.get_created_timeNc           
      C   s   |  t|}| j|}| |}|d| jdkp<| j }| jsN|rN|j	S |rjdj
| jt|dddS | j| jdd}|pi }| D ]\}}	|	r||kr|	||< q|jf |S d	S )
z
        Return public URL or a signed URL for the Blob.

        The existnce of blobs are not verified for public URLs, it makes the code too slow.
        rC   Z
publicReadz {storage_base_url}/{quoted_name}s   /~)safe)Zstorage_base_urlZquoted_nameZv4)Zbucket_bound_hostnamer^   versionN)rh   r   r!   r$   rG   rI   rJ   r]   r[   Z
public_urlr   r   r^   ry   Zgenerate_signed_url)
r'   r   
parametersr$   rL   Zno_signed_urlZdefault_paramsparamskeyr8   r)   r)   r*   url4  s*    



zGoogleCloudStorage.urlc                    s&   t |}| jrt||S t ||S r,   )r   r`   r   r<   get_available_name)r'   r   
max_lengthr?   r)   r*   r   U  s    
z%GoogleCloudStorage.get_available_name)ri   )N)N)rM   rN   rO   r+   rc   rP   re   r!   rh   rl   rt   r~   rG   r   r   r   r   r-   r   r   r   r   r   rQ   r)   r)   r?   r*   rR   h   s*   


	

!rR   )*r3   rp   r   r   datetimer   tempfiler   Zdjango.core.exceptionsr   r   Zdjango.core.files.baser   Zdjango.utilsr   Zdjango.utils.deconstructr   Zstorages.baser	   Zstorages.compressr
   Zstorages.utilsr   r   r   r   r   r   Zgoogle.cloud.exceptionsr   Zgoogle.cloud.storager   r   Zgoogle.cloud.storage.blobr   Zgoogle.cloud.storage.retryr   ImportErrorrx   rw   r   rR   r)   r)   r)   r*   <module>   s>   B