
    gK                       U d Z ddlmZ ddl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rddl-m.Z. ddl/m0Z0  ee1      Z2de3d<    e!ejh                        Z5e	ege6f   Z7de3d<   d dZ8 G d de)      Z9 e9       Z:d!dZ; G d de      Z< G d d      Z= G d de      Z>y)"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   ValidateFuncc                .    | du xr |du xs
 | duxr |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 )abs     a/var/www/openai/venv/lib/python3.12/site-packages/streamlit/runtime/caching/cache_resource_api.py_equal_validate_funcsr&   <   s)     I#!t)I$)H1D=I    c                  F    e Zd ZdZd Z	 	 	 	 	 	 	 	 	 	 	 	 ddZddZd	dZy)
ResourceCachesz#Manages all ResourceCache instancesc                D    t        j                         | _        i | _        y N)	threadingLock_caches_lock_function_cachesselfs    r%   __init__zResourceCaches.__init__H   s    %NN,:<r'   c                   |t         j                  }t        |      }| j                  5  | j                  j                  |      }|?|j                  |k(  r0|j                  |k(  r!t        |j                  |      r|cddd       S t        j                  d|       t        |||||      }|| j                  |<   |cddd       S # 1 sw Y   yxY w)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))keydisplay_namemax_entriesttl_secondsvalidate)mathinfr   r.   r/   getr7   r6   r&   r8   r   debugResourceCache)r1   r4   r5   r6   ttlr8   r7   caches           r%   	get_cachezResourceCaches.get_cacheL   s     ((K%c* ))--c2E!%%4%%4)%..(C  MM?E!)''!E */D!!#&) s   AC6CCc                T    | j                   5  i | _        ddd       y# 1 sw Y   yxY w)zClear all resource caches.N)r.   r/   r0   s    r%   	clear_allzResourceCaches.clear_allu   s    $&D! s   'c                    | j                   5  | j                  j                         }d d d        g }j                         D ]!  }|j	                  |j                                # t        |      S # 1 sw Y   JxY wr+   )r.   r/   copyvaluesextend	get_statsr   )r1   function_cachesstatsr?   s       r%   rG   zResourceCaches.get_statsz   sg     #3388:O 
 "$$++-ELL*+ .5!! s   A11A:N)r4   strr5   rJ   r6   zint | float | Noner>   float | timedelta | str | Noner8   ValidateFunc | Nonereturnr=   rM   NonerM   zlist[CacheStat])__name__
__module____qualname____doc__r2   r@   rB   rG   r"   r'   r%   r)   r)   E   sT    -='' ' (	'
 ,' &' 
'R'
	"r'   r)   c                     t         S )z>Return the StatsProvider for all @st.cache_resource functions.)_resource_cachesr"   r'   r%   !get_resource_cache_stats_providerrW      s    r'   c                  |     e Zd ZdZ	 d	 	 	 	 	 	 	 	 	 	 	 d fdZed	d       Zed
d       Zedd       ZddZ	 xZ
S )CachedResourceFuncInfoz>Implements the CachedFuncInfo interface for @st.cache_resourcec                T    t         |   |||       || _        || _        || _        y )N)show_spinner
hash_funcs)superr2   r6   r>   r8   )r1   funcr[   r6   r>   r8   r\   	__class__s          r%   r2   zCachedResourceFuncInfo.__init__   s8     	%! 	 	

 ' r'   c                "    t         j                  S r+   )r   RESOURCEr0   s    r%   
cache_typez!CachedResourceFuncInfo.cache_type   s    !!!r'   c                    t         S r+   )!CACHE_RESOURCE_MESSAGE_REPLAY_CTXr0   s    r%   cached_message_replay_ctxz0CachedResourceFuncInfo.cached_message_replay_ctx   s    00r'   c                `    | j                   j                   d| j                   j                   S )z-A human-readable name for the cached function.)r^   rR   rS   r0   s    r%   r5   z#CachedResourceFuncInfo.display_name   s+     ))&&'q)?)?(@AAr'   c                    t         j                  || j                  | j                  | j                  | j
                        S )N)r4   r5   r6   r>   r8   )rV   r@   r5   r6   r>   r8   )r1   function_keys     r%   get_function_cachez)CachedResourceFuncInfo.get_function_cache   s=    ))**((]] * 
 	
r'   r+   )r^   ztypes.FunctionTyper[   
bool | strr6   
int | Noner>   rK   r8   rL   r\   HashFuncsDict | None)rM   r   )rM   r   )rM   rJ   )ri   rJ   rM   r   )rQ   rR   rS   rT   r2   propertyrb   re   r5   rj   __classcell__r_   s   @r%   rY   rY      s    H ,0! ! !!  	!
 ,! &! )!$ " " 1 1 B B
r'   rY   c                      e Zd ZdZddZ ededef         Ze	dd       Z
e	ddddd	dd
	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Z
	 dddddd	dd
	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ
dd	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ ed      dd       Zy)CacheResourceAPIzvImplements the public st.cache_resource API: the @st.cache_resource decorator,
    and st.cache_resource.clear().
    c                :    t        || j                        | _        y)zCreate a CacheResourceAPI instance.

        Parameters
        ----------
        decorator_metric_name
            The metric name to record for decorator usage.
        N)r   
_decorator)r1   decorator_metric_names     r%   r2   zCacheResourceAPI.__init__   s     ))>Pr'   F.)boundc                     y r+   r"   )r1   r^   s     r%   __call__zCacheResourceAPI.__call__   s    &)r'   NTFr>   r6   r[   r8   experimental_allow_widgetsr\   c                    y r+   r"   )r1   r>   r6   r[   r8   r{   r\   s          r%   ry   zCacheResourceAPI.__call__   s     r'   c          	     2    | j                  |||||||      S )Nrz   )rt   r1   r^   r>   r6   r[   r8   r{   r\   s           r%   ry   zCacheResourceAPI.__call__   s/     #%'A!  
 	
r'   )r\   c          
         |rt        d       |	fdS t        t        t        t        j
                  |                  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_resourcec           
     8    t        t        |             S )Nr^   r[   r6   r>   r8   r\   )r   rY   )fr\   r6   r[   r>   r8   s    r%   <lambda>z-CacheResourceAPI._decorator.<locals>.<lambda>  s%    5&!- +%)	r'   r   )r   r   rY   r	   typesFunctionTyper~   s     ```` `r%   rt   zCacheResourceAPI._decorator   sY    L &*+;< <	 	 ("%,,d3)'!%	
 		
r'   clear_resource_cachesc                ,    t         j                          y)z Clear all cache_resource caches.N)rV   rB   r0   s    r%   clearzCacheResourceAPI.clear  s     	""$r'   )ru   rJ   )r^   rv   rM   rv   )r>   rK   r6   rl   r[   rk   r8   rL   r{   boolr\   rm   rM   zCallable[[F], F]r+   )r^   zF | Noner>   rK   r6   rl   r[   rk   r8   rL   r{   r   r\   rm   rN   )rQ   rR   rS   rT   r2   r   r   r   rv   r
   ry   rt   r   r   r"   r'   r%   rr   rr      sz   Q  	8CH-.A ) )  /3"&#'(,+0+/	 ,	  		
 !	 &	 %)	 )	 
	 	 
 /3"&#'(,+0+/

 ,	

  
 !
 &
 %)
 )
< ,0@
@
 ,	@

  @
 !@
 &@
 %)@
 )@
D +,% -%r'   rr   c                       e Zd ZdZ	 	 	 	 	 	 	 	 	 	 d
 fdZedd       Zedd       ZddZ e	d      dd       Z
dddZdd	Z xZS )r=   z>Manages cached values for a single st.cache_resource function.c                    t         |           || _        || _        t	        ||t
        j                        | _        t        j                         | _
        || _        y )N)maxsizer>   timer)r]   r2   r4   r5   r   r   TTLCACHE_TIMER
_mem_cacher,   r-   _mem_cache_lockr8   )r1   r4   r6   r7   r8   r5   r_   s         r%   r2   zResourceCache.__init__  sP     	(7?[8R8R8
  )~~/ r'   c                .    | j                   j                  S r+   )r   r   r0   s    r%   r6   zResourceCache.max_entries  s    &&&r'   c                .    | j                   j                  S r+   )r   r>   r0   s    r%   r7   zResourceCache.ttl_seconds  s    """r'   c                   | j                   5  || j                  vr
t               | j                  |   }| j                  2| j                  |j                        s| j                  |= t               |cddd       S # 1 sw Y   yxY w)zRead a value and associated messages from the cache.
        Raise `CacheKeyNotFoundError` if the value doesn't exist.
        N)r   r   r   r8   value)r1   r4   results      r%   read_resultzResourceCache.read_result  sm     !!$//)+--__S)F}}(v||1LOOC(+-- "!!s   A'A>>B_cache_resource_objectc                    t         j                  j                  }t         j                  j                  }| j                  5  t        ||||      | j                  |<   ddd       y# 1 sw Y   yxY w)z3Write a value and associated messages to the cache.N)st_mainidsidebarr   r   r   )r1   r4   r   messagesmain_id
sidebar_ids         r%   write_resultzResourceCache.write_result  sL     ((++ZZ]]
!!#/x*#UDOOC  "!!s   A&&A/c                    | j                   5  || j                  j                          n|| j                  v r| j                  |= d d d        y # 1 sw Y   y xY wr+   )r   r   r   )r1   r4   s     r%   _clearzResourceCache._clear  sD    !!{%%''OOC(	 "!!s   9AAc           
         | j                   5  t        | j                  j                               }d d d        ddlm} D cg c]   }t        d| j                   ||            " c}S # 1 sw Y   ;xY wc c}w )Nr   )asizeofst_cache_resource)category_name
cache_namebyte_length)r   listr   rE    streamlit.vendor.pympler.asizeofr   r   r5   )r1   cache_entriesr   entrys       r%   rG   zResourceCache.get_stats  sy     !! !7!7!9:M " 	= '
 ' 1,,#EN
 '
 	
 "!
s   $A+%A7+A4)
r4   rJ   r6   floatr7   r   r8   rL   r5   rJ   )rM   r   )r4   rJ   rM   r   )r4   rJ   r   r   r   zlist[MsgData]rM   rO   r+   )r4   z
str | NonerM   rO   rP   )rQ   rR   rS   rT   r2   rn   r6   r7   r   r   r   r   rG   ro   rp   s   @r%   r=   r=     s    H!! ! 	!
 &! !" ' ' # #$ ,-V .V)
r'   r=   )r#   rL   r$   rL   rM   r   )rM   r   )?rT   
__future__r   r9   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   datetimer   !streamlit.runtime.caching.hashingr   rQ   r   __annotations__ra   rd   r   r    r&   r)   rV   rW   rY   rr   r=   r"   r'   r%   <module>r      s    ( "    O O O  '  ' 1 H : 
  : N N /"?H% % %?y?Q?Q$R !"C5$;/i /J>"' >"D "# 
)
^ )
XB% B%JO
E O
r'   