U
    Zfg                  
   @   s   d dl Z d dlZd dlZd dlmZ eeZz d dlm	Z	 d dl
mZmZ W n, ek
rz Z zedeW 5 dZ[X Y nX G dd deZdS )    N)	BaseCache)AnonymousCredentials)storage
exceptionsz$no google-cloud-storage module foundc                       s   e Zd ZdZd" fdd	Zedd Zd	d
 Zd#ddZd$ddZ	dd Z
dd Zdd Zdd Zd%ddZdd Zdd Zdd Zd&d d!Z  ZS )'GoogleCloudStorageCachea  Uses an Google Cloud Storage bucket as a cache backend.
    Note: User-contributed functionality. This project does not guarantee that
    this functionality will be maintained or functional at any given time.
    Note: Cache keys must meet GCS criteria for a valid object name (a sequence
    of Unicode characters whose UTF-8 encoding is at most 1024 bytes long).
    Note: Expired cache objects are not automatically purged. If
    delete_expired_objects_on_read=True, they will be deleted following an
    attempted read (which reduces performance). Otherwise, you have to delete
    stale objects yourself. Consider an GCS bucket lifecycle rule or other
    out-of-band process. For example you can use the following rule.
    {"rule": [{"action": {"type": "Delete"}, "condition": {"daysSinceCustomTime": 0}}]}
    https://cloud.google.com/storage/docs/lifecycle#dayssincecustomtime
    :param bucket: Required. Name of the bucket to use. It must already exist.
    :param key_prefix: A prefix that should be added to all keys.
    :param default_timeout: the default timeout that is used if no timeout is
                            specified on :meth:`~BaseCache.set`. A timeout of
                            0 indicates that the cache never expires.
    :param delete_expired_objects_on_read: If True, if a read finds a stale
                                           object, it will be deleted before
                                           a response is returned. Will slow
                                           down responses.
    :param anonymous: If true, use anonymous credentials. Useful for testing.
    Any additional keyword arguments will be passed to ``google.cloud.storage.Client``.
    N,  Fc                    st   t  | t|tstd|r>tjf t dd|| _ntjf || _| j	|| _
|p`d| _|| _|| _d S )Nz*GCSCache bucket parameter must be a stringtest)credentialsproject )super__init__
isinstancestr
ValueErrorr   ZClientr   _clientZ
get_bucketbucket
key_prefixdefault_timeoutdelete_expired_objects_on_read)selfr   r   r   r   Z	anonymouskwargs	__class__ Q/tmp/pip-unpacked-wheel-0x57cbey/flask_caching/contrib/googlecloudstoragecache.pyr   ,   s    	
 

z GoogleCloudStorageCache.__init__c                 C   s0   | d|d  |d}|r&||d< | ||S )Nr   ZCACHE_GCS_BUCKETZCACHE_KEY_PREFIXr   )insertget)clsZappconfigargsr   r   r   r   r   factoryC   s
    
zGoogleCloudStorageCache.factoryc                 C   s   d }d}d}| j | }| j|}|d k	r|jo<|  |jk}|rT| jr| | n<z$| }d}|jdkrvt	
|}W n tjk
r   Y nX |rdnd}td||| |S )NFZmisshitapplication/json	(expired)r   zget key %r -> %s %s)r   r   get_blobcustom_time_nowr   _deleteZdownload_as_bytescontent_typejsonloadsr   NotFoundloggerdebug)r   keyresultexpiredZhit_or_missfull_keyblob
expiredstrr   r   r   r   K   s(    

zGoogleCloudStorageCache.getc              	   C   s   d}| j | }d}zt|}W n ttfk
r<   d}Y nX | j|}|d krX| j}|dkrn| j|d|_	z|j
||d d}W n tjk
r   Y nX td|| |S )	NFr#   zapplication/octet-streamr   )delta)r)   Tzset key %r -> %s)r   r*   dumpsUnicodeDecodeError	TypeErrorr   r3   r   r'   r&   Zupload_from_stringr   TooManyRequestsr-   r.   )r   r/   valuetimeoutr0   r2   r)   r3   r   r   r   setc   s&    

zGoogleCloudStorageCache.setc                 C   s6   | j | }| |r$td| dS | |||S d S )Nzadd key %r -> not addedF)r   _hasr-   r.   r<   )r   r/   r:   r;   r2   r   r   r   addz   s
    

zGoogleCloudStorageCache.addc                 C   s   | j | }| |S N)r   r(   r   r/   r2   r   r   r   delete   s    
zGoogleCloudStorageCache.deletec                    s      fdd|D S )Nc                 3   s   | ]} j | V  qd S r?   )r   ).0r/   r   r   r   	<genexpr>   s     z6GoogleCloudStorageCache.delete_many.<locals>.<genexpr>_delete_many)r   keysr   rC   r   delete_many   s    z#GoogleCloudStorageCache.delete_manyc                 C   s   | j | }| |S r?   )r   r=   r@   r   r   r   has   s    
zGoogleCloudStorageCache.hasc                 C   s   | j ddS )NT)	clear_all)_prunerC   r   r   r   clear   s    zGoogleCloudStorageCache.clearc                 C   s   d}|   }| jj| j| jdd}g }|D ]F}|sB|jr*|j|k r*||j |d7 }t|dkr*| 	| g }q*|r| 	| t
d| dS )Nr   z$items(name,customTime),nextPageToken)prefixfields   d   zevicted %d key(s)T)r'   r   Z
list_blobsr   r   r&   appendnamelenrF   r-   r.   )r   rJ   ZnremovednowZresponse_iteratorZ	to_deleter3   r   r   r   rK      s&    

zGoogleCloudStorageCache._prunec                 C   s   |  |gS r?   rE   )r   r/   r   r   r   r(      s    zGoogleCloudStorageCache._deletec              	   C   sR   z0| j   |D ]}| j| qW 5 Q R X W n tjtjfk
rL   Y nX dS )NT)r   batchr   Zdelete_blobr   r,   r9   )r   rG   r/   r   r   r   rF      s    z$GoogleCloudStorageCache._delete_manyc                 C   sj   d}d}| j |}|d k	rJ|jo.|  |jk}|rF| jrJ| | nd}|rRdnd}td||| |S )NFTr$   r   zhas key %r -> %s %s)r   r%   r&   r'   r   r(   r-   r.   )r   r/   r0   r1   r3   r4   r   r   r   r=      s    zGoogleCloudStorageCache._hasr   c                 C   s   t j t jjt j|d S )N)seconds)datetimerT   timezoneutc	timedelta)r   r5   r   r   r   r'      s    zGoogleCloudStorageCache._now)Nr   FF)N)N)F)r   )__name__
__module____qualname____doc__r   classmethodr!   r   r<   r>   rA   rH   rI   rL   rK   r(   rF   r=   r'   __classcell__r   r   r   r   r      s(       



	r   )rW   r*   loggingZflask_caching.backends.baser   	getLoggerr[   r-   Zgoogle.auth.credentialsr   Zgoogle.cloudr   r   ImportErroreRuntimeErrorr   r   r   r   r   <module>   s   
