o
    hK                     @  s  U d Z ddlmZ ddlZddlZddlmZmZmZm	Z	m
Z
mZmZ ddlmZ ddlm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mZmZ ddlm Z m!Z!m"Z"m#Z# ddl$m%Z% ddl&m'Z'm(Z(m)Z) ddl*m+Z+ erddl,Z,ddl-m.Z. ddl/m0Z0 ee1Z2de3d< e ej4Z5eege6f Z7de3d< d(ddZ8G dd de(Z9e9 Z:d)d d!Z;G d"d# d#eZ<G d$d% d%Z=G d&d' d'eZ>dS )*z"@st.cache_resource implementation.    )annotationsN)TYPE_CHECKINGAnyCallableFinalTypeVarcastoverload)TTLCache)	TypeAlias)
get_logger)cache_utils)CacheKeyNotFoundError)	CacheType)CacheCachedFuncInfomake_cached_func_wrapper)CachedMessageReplayContextCachedResultMsgDatashow_widget_replay_deprecation)gather_metrics)	CacheStatCacheStatsProvidergroup_stats)time_to_seconds)	timedelta)HashFuncsDictr   _LOGGERr   ValidateFuncaValidateFunc | Nonebreturnboolc                 C  s    | du r|du p| duo|duS )zTrue if the two validate functions are equal for the purposes of
    determining whether a given function cache needs to be recreated.
    N )r    r"   r%   r%   `/var/www/vscode/kcb/lib/python3.10/site-packages/streamlit/runtime/caching/cache_resource_api.py_equal_validate_funcs<   s    r'   c                   @  s6   e Zd ZdZdd ZdddZdddZdddZdS )ResourceCachesz$Manages all ResourceCache instances.c                 C  s   t  | _i | _d S N)	threadingLock_caches_lock_function_cachesselfr%   r%   r&   __init__H   s   

zResourceCaches.__init__keystrdisplay_namemax_entriesint | float | Nonettlfloat | timedelta | str | Nonevalidater!   r#   ResourceCachec                 C  s   |du rt j}t|}| jA | j|}|dur2|j|kr2|j|kr2t|j	|r2|W  d   S t
d| t|||||d}|| j|< |W  d   S 1 sRw   Y  dS )zvReturn the mem cache for the given key.

        If it doesn't exist, create a new one with the given params.
        Nz#Creating new ResourceCache (key=%s))r1   r3   r4   ttl_secondsr8   )mathinfr   r,   r-   getr:   r4   r'   r8   r   debugr9   )r/   r1   r3   r4   r6   r8   r:   cacher%   r%   r&   	get_cacheL   s.   



$zResourceCaches.get_cacheNonec                 C  s2   | j  i | _W d   dS 1 sw   Y  dS )zClear all resource caches.N)r,   r-   r.   r%   r%   r&   	clear_allu   s   "zResourceCaches.clear_alllist[CacheStat]c                 C  sX   | j  | j }W d    n1 sw   Y  g }| D ]	}||  qt|S r)   )r,   r-   copyvaluesextend	get_statsr   )r/   function_cachesstatsr?   r%   r%   r&   rG   z   s   zResourceCaches.get_statsN)r1   r2   r3   r2   r4   r5   r6   r7   r8   r!   r#   r9   r#   rA   r#   rC   )__name__
__module____qualname____doc__r0   r@   rB   rG   r%   r%   r%   r&   r(   E   s    

)r(   r   c                   C     t S )z>Return the StatsProvider for all @st.cache_resource functions.)_resource_cachesr%   r%   r%   r&   !get_resource_cache_stats_provider      rR   c                      sZ   e Zd ZdZ	dd  fddZed!ddZed"ddZed#ddZd$ddZ	  Z
S )%CachedResourceFuncInfoz?Implements the CachedFuncInfo interface for @st.cache_resource.Nfunctypes.FunctionTypeshow_spinner
bool | strr4   
int | Noner6   r7   r8   r!   
hash_funcsHashFuncsDict | Nonec                   s(   t  j|||d || _|| _|| _d S )N)rW   rZ   )superr0   r4   r6   r8   )r/   rU   rW   r4   r6   r8   rZ   	__class__r%   r&   r0      s   	
zCachedResourceFuncInfo.__init__r#   r   c                 C  s   t jS r)   )r   RESOURCEr.   r%   r%   r&   
cache_type   s   z!CachedResourceFuncInfo.cache_typer   c                 C  rP   r)   )!CACHE_RESOURCE_MESSAGE_REPLAY_CTXr.   r%   r%   r&   cached_message_replay_ctx   rS   z0CachedResourceFuncInfo.cached_message_replay_ctxr2   c                 C  s   | j j d| j j S )z.A human-readable name for the cached function..)rU   rM   rN   r.   r%   r%   r&   r3      s   z#CachedResourceFuncInfo.display_namefunction_keyr   c                 C  s   t j|| j| j| j| jdS )N)r1   r3   r4   r6   r8   )rQ   r@   r3   r4   r6   r8   )r/   rd   r%   r%   r&   get_function_cache   s   z)CachedResourceFuncInfo.get_function_cacher)   )rU   rV   rW   rX   r4   rY   r6   r7   r8   r!   rZ   r[   )r#   r   )r#   r   )r#   r2   )rd   r2   r#   r   )rL   rM   rN   rO   r0   propertyr`   rb   r3   re   __classcell__r%   r%   r]   r&   rT      s    	rT   c                   @  s   e Zd ZdZd(ddZededef dZe	d)ddZ
e	dddddddd*ddZ
	d+dddddddd,d dZ
dd!d,d"d#Zed$d-d&d'ZdS ).CacheResourceAPIzvImplements the public st.cache_resource API: the @st.cache_resource decorator,
    and st.cache_resource.clear().
    decorator_metric_namer2   c                 C  s   t || j| _dS )zCreate a CacheResourceAPI instance.

        Parameters
        ----------
        decorator_metric_name
            The metric name to record for decorator usage.
        N)r   
_decorator)r/   ri   r%   r%   r&   r0      s   zCacheResourceAPI.__init__F.)boundrU   r#   c                 C     d S r)   r%   )r/   rU   r%   r%   r&   __call__   s   zCacheResourceAPI.__call__NTFr6   r4   rW   r8   experimental_allow_widgetsrZ   r6   r7   r4   rY   rW   rX   r8   r!   rp   r$   rZ   r[   Callable[[F], F]c                C  rm   r)   r%   )r/   r6   r4   rW   r8   rp   rZ   r%   r%   r&   rn      s   
F | Nonec             	   C  s   | j |||||||dS )Nro   )rj   r/   rU   r6   r4   rW   r8   rp   rZ   r%   r%   r&   rn      s   )rZ   c             	     sF   |rt d |du r fddS tttd| dS )a1  Decorator to cache functions that return global resources (e.g. database connections, ML models).

        Cached objects are shared across all users, sessions, and reruns. They
        must be thread-safe because they can be accessed from multiple threads
        concurrently. If thread safety is an issue, consider using ``st.session_state``
        to store resources per session instead.

        You can clear a function's cache with ``func.clear()`` or clear the entire
        cache with ``st.cache_resource.clear()``.

        A function's arguments must be hashable to cache it. If you have an
        unhashable argument (like a database connection) or an argument you
        want to exclude from caching, use an underscore prefix in the argument
        name. In this case, Streamlit will return a cached value when all other
        arguments match a previous function call. Alternatively, you can
        declare custom hashing functions with ``hash_funcs``.

        To cache data, use ``st.cache_data`` instead. Learn more about caching at
        https://docs.streamlit.io/develop/concepts/architecture/caching.

        Parameters
        ----------
        func : callable
            The function that creates the cached resource. Streamlit hashes the
            function's source code.

        ttl : float, timedelta, str, or None
            The maximum time to keep an entry in the cache. Can be one of:

            - ``None`` if cache entries should never expire (default).
            - A number specifying the time in seconds.
            - A string specifying the time in a format supported by `Pandas's
              Timedelta constructor <https://pandas.pydata.org/docs/reference/api/pandas.Timedelta.html>`_,
              e.g. ``"1d"``, ``"1.5 days"``, or ``"1h23s"``.
            - A ``timedelta`` object from `Python's built-in datetime library
              <https://docs.python.org/3/library/datetime.html#timedelta-objects>`_,
              e.g. ``timedelta(days=1)``.

        max_entries : int or None
            The maximum number of entries to keep in the cache, or None
            for an unbounded cache. When a new entry is added to a full cache,
            the oldest cached entry will be removed. Defaults to None.

        show_spinner : bool or str
            Enable the spinner. Default is True to show a spinner when there is
            a "cache miss" and the cached resource is being created. If string,
            value of show_spinner param will be used for spinner text.

        validate : callable or None
            An optional validation function for cached data. ``validate`` is called
            each time the cached value is accessed. It receives the cached value as
            its only parameter and it must return a boolean. If ``validate`` returns
            False, the current cached value is discarded, and the decorated function
            is called to compute a new value. This is useful e.g. to check the
            health of database connections.

        experimental_allow_widgets : bool
            Allow widgets to be used in the cached function. Defaults to False.

        hash_funcs : dict or None
            Mapping of types or fully qualified names to hash functions.
            This is used to override the behavior of the hasher inside Streamlit's
            caching mechanism: when the hasher encounters an object, it will first
            check to see if its type matches a key in this dict and, if so, will use
            the provided function to generate a hash for it. See below for an example
            of how this can be used.

        .. deprecated::
            The cached widget replay functionality was removed in 1.38. Please
            remove the ``experimental_allow_widgets`` parameter from your
            caching decorators. This parameter will be removed in a future
            version.

        Example
        -------
        >>> import streamlit as st
        >>>
        >>> @st.cache_resource
        ... def get_database_session(url):
        ...     # Create a database session object that points to the URL.
        ...     return session
        >>>
        >>> s1 = get_database_session(SESSION_URL_1)
        >>> # Actually executes the function, since this is the first time it was
        >>> # encountered.
        >>>
        >>> s2 = get_database_session(SESSION_URL_1)
        >>> # Does not execute the function. Instead, returns its previously computed
        >>> # value. This means that now the connection object in s1 is the same as in s2.
        >>>
        >>> s3 = get_database_session(SESSION_URL_2)
        >>> # This is a different URL, so the function executes.

        By default, all parameters to a cache_resource function must be hashable.
        Any parameter whose name begins with ``_`` will not be hashed. You can use
        this as an "escape hatch" for parameters that are not hashable:

        >>> import streamlit as st
        >>>
        >>> @st.cache_resource
        ... def get_database_session(_sessionmaker, url):
        ...     # Create a database connection object that points to the URL.
        ...     return connection
        >>>
        >>> s1 = get_database_session(create_sessionmaker(), DATA_URL_1)
        >>> # Actually executes the function, since this is the first time it was
        >>> # encountered.
        >>>
        >>> s2 = get_database_session(create_sessionmaker(), DATA_URL_1)
        >>> # Does not execute the function. Instead, returns its previously computed
        >>> # value - even though the _sessionmaker parameter was different
        >>> # in both calls.

        A cache_resource function's cache can be procedurally cleared:

        >>> import streamlit as st
        >>>
        >>> @st.cache_resource
        ... def get_database_session(_sessionmaker, url):
        ...     # Create a database connection object that points to the URL.
        ...     return connection
        >>>
        >>> fetch_and_clean_data.clear(_sessionmaker, "https://streamlit.io/")
        >>> # Clear the cached entry for the arguments provided.
        >>>
        >>> get_database_session.clear()
        >>> # Clear all cached entries for this function.

        To override the default hashing behavior, pass a custom hash function.
        You can do that by mapping a type (e.g. ``Person``) to a hash
        function (``str``) like this:

        >>> import streamlit as st
        >>> from pydantic import BaseModel
        >>>
        >>> class Person(BaseModel):
        ...     name: str
        >>>
        >>> @st.cache_resource(hash_funcs={Person: str})
        ... def get_person_name(person: Person):
        ...     return person.name

        Alternatively, you can map the type's fully-qualified name
        (e.g. ``"__main__.Person"``) to the hash function instead:

        >>> import streamlit as st
        >>> from pydantic import BaseModel
        >>>
        >>> class Person(BaseModel):
        ...     name: str
        >>>
        >>> @st.cache_resource(hash_funcs={"__main__.Person": str})
        ... def get_person_name(person: Person):
        ...     return person.name
        cache_resourceNc              	     s   t t|  dS )NrU   rW   r4   r6   r8   rZ   )r   rT   )frZ   r4   rW   r6   r8   r%   r&   <lambda>  s    z-CacheResourceAPI._decorator.<locals>.<lambda>rV   ru   )r   r   rT   r   rs   r%   rw   r&   rj      s    'zCacheResourceAPI._decoratorclear_resource_cachesrA   c                 C  s   t   dS )z Clear all cache_resource caches.N)rQ   rB   r.   r%   r%   r&   clear  s   zCacheResourceAPI.clear)ri   r2   )rU   rk   r#   rk   )r6   r7   r4   rY   rW   rX   r8   r!   rp   r$   rZ   r[   r#   rq   r)   )rU   rr   r6   r7   r4   rY   rW   rX   r8   r!   rp   r$   rZ   r[   rJ   )rL   rM   rN   rO   r0   r   r   r   rk   r	   rn   rj   r   rz   r%   r%   r%   r&   rh      s8    
 Crh   c                      sp   e Zd ZdZd# fd
dZed$ddZed$ddZd%ddZe	dd&ddZ
d'd(ddZd)d!d"Z  ZS )*r9   z>Manages cached values for a single st.cache_resource function.r1   r2   r4   floatr:   r8   r!   r3   c                   s<   t    || _|| _t||tjd| _t	 | _
|| _d S )N)maxsizer6   timer)r\   r0   r1   r3   r
   r   TTLCACHE_TIMER
_mem_cacher*   r+   _mem_cache_lockr8   )r/   r1   r4   r:   r8   r3   r]   r%   r&   r0     s   


zResourceCache.__init__r#   c                 C     | j jS r)   )r   r|   r.   r%   r%   r&   r4        zResourceCache.max_entriesc                 C  r   r)   )r   r6   r.   r%   r%   r&   r:     r   zResourceCache.ttl_secondsr   c                 C  sl   | j ) || jvrt | j| }| jdur#| |js#| j|= t |W  d   S 1 s/w   Y  dS )zRead a value and associated messages from the cache.
        Raise `CacheKeyNotFoundError` if the value doesn't exist.
        N)r   r   r   r8   value)r/   r1   resultr%   r%   r&   read_result  s   

$zResourceCache.read_result_cache_resource_objectr   r   messageslist[MsgData]rA   c                 C  sP   t jj}t jj}| j t||||| j|< W d   dS 1 s!w   Y  dS )z3Write a value and associated messages to the cache.N)st_mainidsidebarr   r   r   )r/   r1   r   r   main_id
sidebar_idr%   r%   r&   write_result  s
   "zResourceCache.write_resultN
str | Nonec                 C  sr   | j , |d u r| j  n|| jv r| j|= W d    d S W d    d S W d    d S 1 s2w   Y  d S r)   )r   r   rz   )r/   r1   r%   r%   r&   _clear  s   

"zResourceCache._clearrC   c                   sT   j  tj }W d    n1 sw   Y  ddlm   fdd|D S )Nr   )asizeofc                   s    g | ]}t d j |dqS )st_cache_resource)category_name
cache_namebyte_length)r   r3   ).0entryr   r/   r%   r&   
<listcomp>  s    z+ResourceCache.get_stats.<locals>.<listcomp>)r   listr   rE    streamlit.vendor.pympler.asizeofr   )r/   cache_entriesr%   r   r&   rG     s   zResourceCache.get_stats)
r1   r2   r4   r{   r:   r{   r8   r!   r3   r2   )r#   r{   )r1   r2   r#   r   )r1   r2   r   r   r   r   r#   rA   r)   )r1   r   r#   rA   rK   )rL   rM   rN   rO   r0   rf   r4   r:   r   r   r   r   rG   rg   r%   r%   r]   r&   r9     s    
r9   )r    r!   r"   r!   r#   r$   )r#   r   )?rO   
__future__r   r;   r*   typingr   r   r   r   r   r   r	   
cachetoolsr
   typing_extensionsr   	streamlitr   streamlit.loggerr   streamlit.runtime.cachingr   &streamlit.runtime.caching.cache_errorsr   $streamlit.runtime.caching.cache_typer   %streamlit.runtime.caching.cache_utilsr   r   r   /streamlit.runtime.caching.cached_message_replayr   r   r   r   streamlit.runtime.metrics_utilr   streamlit.runtime.statsr   r   r   streamlit.time_utilr   typesdatetimer   !streamlit.runtime.caching.hashingr   rL   r   __annotations__r_   ra   r$   r   r'   r(   rQ   rR   rT   rh   r9   r%   r%   r%   r&   <module>   sB   $

	B
,  