o
    #US`                     @   s   d Z dZe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	ddl
Z
ddlmZ ddlmZmZ ddlmZ eeZdZeejej d	 Zd
dd eeedD ZeradefZn
e dd eD fZdddZ!g fddZ"G dd de#Z$dS )z
    flask.ext.cache
    ~~~~~~~~~~~~~~

    Adds cache support to your application.

    :copyright: (c) 2010 by Thadeus Burgess.
    :license: BSD, see LICENSE for more details
z0.13.1    N)import_string)requestcurrent_app   )PY2z_template_fragment_cache_%s%sz_. c                 c   s    | ]	}|t vr|V  qd S N)valid_chars).0c r   M/home/ubuntu/webapp/venv/lib/python3.10/site-packages/flask_cache/__init__.py	<genexpr>#   s    r      c                 c   s    | ]}|d fV  qd S r   r   )r
   kr   r   r   r   '   s    c           
      C   s>  t | d }d}t| dd}|rt |st| j}n|r,|d dkr,|r,t|d }| j}t| dr8| j}nBt| dd}|rHt |sH|j	}|sPt| dd}|sl|rl|rl|d dkrb|d j	}n
|d dkrl|d }|rw|j
d | j
 }n| j
}d||f}|jt }|rd|||f}	|	jt }	||	fS d}	||	fS )	z;
    Attempts to returns unique namespace for function
    r   N__self__self__qualname__im_classcls.)inspect
getargspecgetattrisclassreprr   
__module__hasattrr   	__class____name__join	translatenull_control)
fargsm_argsinstance_tokeninstance_selfmodulenameklassnsinsr   r   r   function_namespace)   sN   


r-   c                 C   s   |rd|  } t | d|f S )z7
    Make a cache key for a specific fragment name
    z%s__)TEMPLATE_FRAGMENT_KEY_TEMPLATEr    )fragment_namevary_onr   r   r   make_template_fragment_key_   s   r2   c                   @   s   e Zd ZdZd0ddZd1ddZdd	 Ze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d2ddZdd  Zd!d" Z		d3d$d%Zd4d&d'Zd(d) Zd5d*d+Zd,d- Zd.d/ ZdS )6Cachez:
    This class is used to control the cache objects.
    NTc                 C   sH   |d u st |tstd|| _|| _|| _|d ur"| || d S d S )N,`config` must be an instance of dict or None)
isinstancedict
ValueErrorwith_jinja2_extconfigappinit_app)r   r:   r8   r9   r   r   r   __init__p   s   zCache.__init__c                 C   s  |du st |tstd|j }| jr|| j |r"|| |}|dd |dd |dd |d	d |d
d |dd |dg  |dd |dd |d dkri|d sitd | j	rddl
m}m} t|j||  |j| | || dS )z5This is used to initialize cache with your app objectNr4   CACHE_DEFAULT_TIMEOUTi,  CACHE_THRESHOLDi  CACHE_KEY_PREFIXflask_cache_CACHE_MEMCACHED_SERVERS	CACHE_DIRCACHE_OPTIONS
CACHE_ARGS
CACHE_TYPEnullCACHE_NO_NULL_WARNINGFzHFlask-Cache: CACHE_TYPE is set to null, caching is effectively disabled.r   )CacheExtensionJINJA_CACHE_ATTR_NAME)r5   r6   r7   r9   copyupdate
setdefaultwarningswarnr8   	jinja2extrH   rI   setattr	jinja_envadd_extension
_set_cache)r   r:   r9   base_configrH   rI   r   r   r   r;   {   s0   


zCache.init_appc                 C   s   |d }d|vr#ddl m} zt||}W n ty"   td| w t|}|d d d  }d|d i}|d	 r@||d	  t|d
sHi |_|j	di  ||||||jd | < d S )NrE   r   r   )backendsz$%s is not a valid FlaskCache backendrD   default_timeoutr=   rC   
extensionscache)
r   rU   r   AttributeErrorImportErrorr   rK   r   rW   rL   )r   r:   r9   	import_merU   	cache_obj
cache_argscache_optionsr   r   r   rS      s*   
zCache._set_cachec                 C   s   | j pt}|jd |  S )NrX   )r:   r   rW   )r   r:   r   r   r   rX      s   
zCache.cachec                 O      | j j|i |S )Proxy function for internal cache object.)rX   getr   r$   kwargsr   r   r   rb         z	Cache.getc                 O      | j j|i | dS ra   N)rX   setrc   r   r   r   rh         z	Cache.setc                 O   rf   rg   )rX   addrc   r   r   r   rj      ri   z	Cache.addc                 O   rf   rg   )rX   deleterc   r   r   r   rk      ri   zCache.deletec                 O   rf   rg   )rX   delete_manyrc   r   r   r   rl      ri   zCache.delete_manyc                 C   s   | j   dS rg   )rX   clearr   r   r   r   rm      s   zCache.clearc                 O   r_   r`   )rX   get_manyrc   r   r   r   ro      re   zCache.get_manyc                 O   rf   rg   )rX   set_manyrc   r   r   r   rp      ri   zCache.set_manyview/%sc                        fdd}|S )a?  
        Decorator. Use this to cache a function. By default the cache key
        is `view/request.path`. You are able to use this decorator with any
        function by changing the `key_prefix`. If the token `%s` is located
        within the `key_prefix` then it will replace that with `request.path`

        Example::

            # An example view function
            @cache.cached(timeout=50)
            def big_foo():
                return big_bar_calc()

            # An example misc function to cache.
            @cache.cached(key_prefix='MyCachedList')
            def get_list():
                return [random.randrange(0, 1) for i in range(50000)]

            my_list = get_list()

        .. note::

            You MUST have a request context to actually called any functions
            that are cached.

        .. versionadded:: 0.4
            The returned decorated function now has three function attributes
            assigned to it. These attributes are readable/writable.

                **uncached**
                    The original undecorated function

                **cache_timeout**
                    The cache timeout value for this function. For a custom value
                    to take affect, this must be set before the function is called.

                **make_cache_key**
                    A function used in generating the cache_key used.

        :param timeout: Default None. If set to an integer, will cache for that
                        amount of time. Unit of time is in seconds.
        :param key_prefix: Default 'view/%(request.path)s'. Beginning key to .
                           use for the cache key.

                           .. versionadded:: 0.3.4
                               Can optionally be a callable which takes no arguments
                               but returns a string that will be used as the cache_key.

        :param unless: Default None. Cache will *always* execute the caching
                       facilities unless this callable is true.
                       This will bypass the caching entirely.
        c                    s>   t  fdd fdd} _ _| _ S )Nc                     s   t r du r| i |S z j| i |}j|}W n ty9   tjr+ td | i | Y S w |d u rl| i |}zjj	|| j
d W |S  tyk   tjr] td | i | Y S w |S NT(Exception possibly due to cache backend.timeoutcallablemake_cache_keyrX   rb   	Exceptionr   debuglogger	exceptionrh   cache_timeoutr$   rd   	cache_keyrvdecorated_functionr#   r   unlessr   r   r     s2   


z;Cache.cached.<locals>.decorator.<locals>.decorated_functionc                     s0   t  r	  }|S d v r tj }|S  }|S )Nz%s)rx   r   path)r$   rd   r   )
key_prefixr   r   ry   4  s   
z7Cache.cached.<locals>.decorator.<locals>.make_cache_key)	functoolswrapsuncachedr~   ry   )r#   ry   r   r   rv   r   r   r#   r   	decorator  s   
zCache.cached.<locals>.decoratorr   )r   rv   r   r   r   r   r   r   cached   s   6+zCache.cachedc                 C   s   |d S )N_memverr   )r   funcnamer   r   r   	_memvnameE  s   zCache._memvnamec                 C   s   t t jd d dS )N   utf-8)base64	b64encodeuuiduuid4bytesdecodern   r   r   r   _memoize_make_version_hashH  s   z Cache._memoize_make_version_hashFc                 C   s   t ||d\}}| |}|g}	|r| |}
|	|
 |r*| j|	d  |dfS t| jj|	 }d}|d du rB|  |d< d}|rR|d du rR|  |d< d}|ra|	dd }	|  g}d}|rp| jjt	t
|	||d |d	|fS )
zY
        Updates the hash version associated with a memoized function or method.
        )r$   NFr   Tr   ru   r   )r-   r   appendrX   rl   listro   r   rp   r6   zipr    )r   r#   r$   resetrk   rv   fnameinstance_fnameversion_key
fetch_keysinstance_version_keyversion_data_listdirtyr   r   r   _memoize_versionK  s4   



zCache._memoize_versionc                    s    fdd}|S )zO
        Function used to create the cache_key for memoized functions.
        c                    s   t d}j| ||d\}}t r |}n|}t| r.j| g|R i |\}}n||}}z	d|||}	W n tyL   d|||f }	Y nw t }
|
|		d t
|
 d d }
|
d}
|
|7 }
|
S )Nr~   )r$   rv   z	{0}{1}{2}z%s%s%sr      )r   r   rx   _memoize_kwargs_to_argsformatrY   hashlibmd5rK   encoder   r   digestr   )r#   r$   rd   _timeoutr   version_dataaltfnamekeyargs	keykwargsupdatedr   	make_namer   rv   r   r   ry   z  s2   



z5Cache._memoize_make_cache_key.<locals>.make_cache_keyr   )r   r   rv   ry   r   r   r   _memoize_make_cache_keyv  s   zCache._memoize_make_cache_keyc           
      O   s   g }d}t |}t|j}t|D ]X}|dkr*|j| dv r*t|d }	|d7 }n;|j| |v r9||j|  }	n,|t|k rH|| }	|d7 }nt|| t|jkr_|j||  }	|d7 }nd }	|d7 }||	 qt	|i fS )Nr   )r   r   r   )
r   r   lenr$   ranger   absdefaultsr   tuple)
r   r#   r$   rd   new_argsarg_numargspecargs_leniargr   r   r   r     s(   




zCache._memoize_kwargs_to_argsc                    rr   )a[  
        Use this to cache the result of a function, taking its arguments into
        account in the cache key.

        Information on
        `Memoization <http://en.wikipedia.org/wiki/Memoization>`_.

        Example::

            @cache.memoize(timeout=50)
            def big_foo(a, b):
                return a + b + random.randrange(0, 1000)

        .. code-block:: pycon

            >>> big_foo(5, 2)
            753
            >>> big_foo(5, 3)
            234
            >>> big_foo(5, 2)
            753

        .. versionadded:: 0.4
            The returned decorated function now has three function attributes
            assigned to it.

                **uncached**
                    The original undecorated function. readable only

                **cache_timeout**
                    The cache timeout value for this function. For a custom value
                    to take affect, this must be set before the function is called.

                    readable and writable

                **make_cache_key**
                    A function used in generating the cache_key used.

                    readable and writable


        :param timeout: Default None. If set to an integer, will cache for that
                        amount of time. Unit of time is in seconds.
        :param make_name: Default None. If set this is a function that accepts
                          a single argument, the function name, and returns a
                          new string to be used as the function name. If not set
                          then the function name is used.
        :param unless: Default None. Cache will *always* execute the caching
                       facilities unelss this callable is true.
                       This will bypass the caching entirely.

        .. versionadded:: 0.5
            params ``make_name``, ``unless``
        c                    sJ   t  fdd  _ _  _fdd _ S )Nc                     s   t r du r| i |S z jg| R i |}j|}W n ty=   tjr/ td | i | Y S w |d u rj| i |}zjj	|| j
d W |S  tyi   tjra td Y |S w |S rs   rw   r   r   r   r   r   	  s2   

z:Cache.memoize.<locals>.memoize.<locals>.decorated_functionc                      s
     S r   )delete_memoizedr   )r#   r   r   r   <lambda>'  s   
 z0Cache.memoize.<locals>.memoize.<locals>.<lambda>)r   r   r   r~   r   ry   r   )r#   r   r   rv   r   r   r   memoize  s   zCache.memoize.<locals>.memoizer   )r   rv   r   r   r   r   r   r   r     s   8"zCache.memoizec                 O   s   t |stdz$|s|s| j|dd W dS |j|jg|R i |}| j| W dS  ty?   tj	r7 t
d Y dS w )a  
        Deletes the specified functions caches, based by given parameters.
        If parameters are given, only the functions that were memoized with them
        will be erased. Otherwise all versions of the caches will be forgotten.

        Example::

            @cache.memoize(50)
            def random_func():
                return random.randrange(1, 50)

            @cache.memoize()
            def param_func(a, b):
                return a+b+random.randrange(1, 50)

        .. code-block:: pycon

            >>> random_func()
            43
            >>> random_func()
            43
            >>> cache.delete_memoized('random_func')
            >>> random_func()
            16
            >>> param_func(1, 2)
            32
            >>> param_func(1, 2)
            32
            >>> param_func(2, 2)
            47
            >>> cache.delete_memoized('param_func', 1, 2)
            >>> param_func(1, 2)
            13
            >>> param_func(2, 2)
            47

        Delete memoized is also smart about instance methods vs class methods.

        When passing a instancemethod, it will only clear the cache related
        to that instance of that object. (object uniqueness can be overridden
            by defining the __repr__ method, such as user id).

        When passing a classmethod, it will clear all caches related across
        all instances of that class.

        Example::

            class Adder(object):
                @cache.memoize()
                def add(self, b):
                    return b + random.random()

        .. code-block:: pycon

            >>> adder1 = Adder()
            >>> adder2 = Adder()
            >>> adder1.add(3)
            3.23214234
            >>> adder2.add(3)
            3.60898509
            >>> cache.delete_memoized(adder.add)
            >>> adder1.add(3)
            3.01348673
            >>> adder2.add(3)
            3.60898509
            >>> cache.delete_memoized(Adder.add)
            >>> adder1.add(3)
            3.53235667
            >>> adder2.add(3)
            3.72341788

        :param fname: Name of the memoized function, or a reference to the function.
        :param \*args: A list of positional parameters used with memoized function.
        :param \**kwargs: A dict of named parameters used with memoized function.

        .. note::

            Flask-Cache uses inspect to order kwargs into positional args when
            the function is memoized. If you pass a function reference into ``fname``
            instead of the function name, Flask-Cache will be able to place
            the args/kwargs in the proper order, and delete the positional cache.

            However, if ``delete_memoized`` is just called with the name of the
            function, be sure to pass in potential arguments in the same order
            as defined in your function as args only, otherwise Flask-Cache
            will not be able to compute the same cache key.

        .. note::

            Flask-Cache maintains an internal random version hash for the function.
            Using delete_memoized will only swap out the version hash, causing
            the memoize function to recompute results and put them into another key.

            This leaves any computed caches for this memoized function within the
            caching backend.

            It is recommended to use a very high timeout with memoize if using
            this function, so that when the version has is swapped, the old cached
            results would eventually be reclaimed by the caching backend.
        z_Deleting messages by relative name is no longer reliable, please switch to a function referenceT)r   rt   N)rx   DeprecationWarningr   ry   r   rX   rk   rz   r   r{   r|   r}   )r   r#   r$   rd   r   r   r   r   r   ,  s   ezCache.delete_memoizedc                 G   sL   t |stdz
| j|dd W dS  ty%   tjr td Y dS w )a  
        Delete the version hash associated with the function.

        ..warning::

            Performing this operation could leave keys behind that have
            been created with this version hash. It is up to the application
            to make sure that all keys that may have been created with this
            version hash at least have timeouts so they will not sit orphaned
            in the cache backend.
        zYDeleting messages by relative name is no longer reliable, please use a function referenceT)rk   rt   N)rx   r   r   rz   r   r{   r|   r}   )r   r#   r$   r   r   r   delete_memoized_verhash  s   zCache.delete_memoized_verhash)NTNr   )Nrq   N)NFFN)NN)NNN)r   r   r   __doc__r<   r;   rS   propertyrX   rb   rh   rj   rk   rl   rm   ro   rp   r   r   r   r   r   r   r   r   r   r   r   r   r   r3   k   s4    

(

c

+%
5\ur3   r   )%r   __version____versionfull__r   r   r   r   loggingstringr   rM   werkzeugr   flaskr   r   _compatr   	getLoggerr   r|   r/   rh   ascii_lettersdigitsr	   r    mapchrr   delcharsr"   r6   r-   r2   objectr3   r   r   r   r   <module>   s0   



6