L iaR@UdZddlmZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZmZmZmZmZmZmZddlmZddlmZdd lmZdd lmZdd lmZdd lm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&dd l'm(Z(m)Z)m*Z*m+Z+ddl,m-Z-m.Z.ddl/m0Z0erddl1Z1ddl2m3Z3ddl4m5Z5ee6Z7de8d<ejrZ:edZ;edZ<Gddee<Z=Gddee;ed"dZ?Gddee;e>7R!*!1ct)zRead a value and associated messages from the cache. Raises ------ CacheKeyNotFoundError Raised if value_key is not in the cache. NotImplementedErrorr. value_keys r/ read_resultzCache.read_resultOs "!r1ct)z}Write a value and associated messages to the cache, overwriting any existing result that uses the value_key. r3)r.r6valuemessagess r/ write_resultzCache.write_result[s "!r1cd|j5|j|cdddS#1swYyxYw)apReturn the lock that should be held while computing a new cached value. In a popular app with a cache that hasn't been pre-warmed, many sessions may try to access a not-yet-cached value simultaneously. We use a lock to ensure that only one of those sessions computes the value, and the others block until the value is computed. N)r,r+r5s r/compute_value_lockzCache.compute_value_lockds0 # # 0$$Y/ 0 0 0s&/Nc|j5|s|jjn||jvr |j|=ddd|j|y#1swYxYw)zClear values from this cache. If no argument is passed, all items are cleared from the cache. A key can be passed to clear that key from the cache only. Nkey)r,r+clear_clearr.r@s r/rAz Cache.clearnsc  # # +!!''))))%%c*  +    + +s 9A!!A*ct)z?Subclasses must implement this to perform cache-clearing logic.r3rCs r/rBz Cache._clearzs "!r1returnNone)r6strrFCachedResult[R])r6rHr9r$r:z list[MsgData]rFrG)r6rHrFzthreading.Lockr()r@ str | NonerFrG) __name__ __module__ __qualname____doc__r0rr7r;r=rArBr1r/r&r&HsPF2 " """0 ""r1r&cZeZdZdZ d ddZed dZed dZd dZy) CachedFuncInfozEncapsulates data for a cached function instance. CachedFuncInfo instances are scoped to a single script run - they're not persistent. c<||_||_||_||_yr()func hash_funcs show_spinner show_time)r.rSrTrUrVs r/r0zCachedFuncInfo.__init__s! $("r1ctr(r3r-s r/ cache_typezCachedFuncInfo.cache_type!!r1ctr(r3r-s r/cached_message_replay_ctxz(CachedFuncInfo.cached_message_replay_ctxrYr1ct)z3Get or create the function cache for the given key.r3)r. function_keys r/get_function_cachez!CachedFuncInfo.get_function_cacherYr1N)F) rSzCallable[P, R]rTHashFuncsDict | NonerUz bool | strrVboolrFrG)rFr!)rFr)r]rHrFCache[R]) rKrLrMrNr0propertyrXr[r^rOr1r/rQrQsn # #) #! #  #  #"""""r1rQclt|}tdtj||jS)aaCreate a callable wrapper around a CachedFunctionInfo. Calling the wrapper will return the cached value if it's already been computed, and will call the underlying function to compute and cache the value otherwise. The wrapper also has a `clear` function that can be called to clear some or all of the wrapper's cached values. CachedFunc[P, R]) CachedFuncr functoolsupdate_wrapperrS)info cached_funcs r/make_cached_func_wrapperrjs-T"K "I$<$<[$))$T UUr1c0eZdZdZddZddZd dZd dZy) BoundCachedFuncz|A wrapper around a CachedFunc that binds it to a specific instance in case of decorated function is a class method. c ||_||_yr( _cached_func _instance)r.riinstances r/r0zBoundCachedFunc.__init__s'!r1cB|j|jg|i|Sr(rnr.argskwargss r/__call__zBoundCachedFunc.__call__s# t  A$A&AAr1cdd|jjjd|jdS)Nz)ro_inforSrpr-s r/__repr__zBoundCachedFunc.__repr__s0#D$5$5$;$;$@$@#AdnnEUUVWWr1c|s|r+|jj|jg|i|y|jjyr()rorArprss r/rAzBoundCachedFunc.clearsA 6 $D   # #DNN DT DV D    # # %r1N)rirdrqrrFrGrtP.argsruP.kwargsrFr$rFrHrtrrurrFrG)rKrLrMrNr0rvrzrArOr1r/rlrls"BX&r1rlceZdZd dZddZdddZddZ d ddZddZ ddZ e dd Z e dd Z e dd Z dd Z y)rec\||_t|j|j|_yr()ry_make_function_keyrXrS _function_key)r.rhs r/r0zCachedFunc.__init__s  /Kr1c6d|jjdS)Nz !? A E> A  B-$ E>-B6 2'E>C88E;A/E66E;;E>>Fcyr(rOr-s r/rAzCachedFunc.clearfs r1cyr(rOrss r/rAzCachedFunc.clearis@Cr1cyr(rOrss r/rAzCachedFunc.clearls8;r1c|jj|j}|s|rMt|jj|jj |||jj }nd}|j|y)aClear the cached function's associated cache. If no arguments are passed, Streamlit will clear all values cached for the function. If arguments are passed, Streamlit will clear the cached value for these arguments only. Parameters ---------- *args: Any Arguments of the cached functions. **kwargs: Any Keyword arguments of the cached function. Example ------- >>> import streamlit as st >>> import time >>> >>> @st.cache_data >>> def foo(bar): >>> time.sleep(2) >>> st.write(f"Executed foo({bar}).") >>> return bar >>> >>> if st.button("Clear all cached values for `foo`", on_click=foo.clear): >>> foo.clear() >>> >>> if st.button("Clear the cached value of `foo(1)`"): >>> foo.clear(1) >>> >>> foo(1) >>> foo(2) rNr?)ryr^rrrXrSrTrA)r.rtrurr@s r/rAzCachedFunc.clearosnH --d.@.@A 6!::00ZZ__"::00 CC  r1)rhCachedFuncInfo[P, R]rFrGrr()rqrrz Any | NonerFrr|)rtuple[Any, ...]rdict[str, Any]rrJrFr$)rrIrFr$) rrar6rHrrrrrFr$rE)rtr}rur~rFrGr) rKrLrMr0rzrrvrrrr rArOr1r/reresL2O O&'+ (U"(U$(U$ (U (UT III# I $ I IV   CC ;;/r1rec 8g}tt|D]$}t||}|j|||f&|j D]\}} |j|| ft j dd} |D]O\}} |(|jdrtjd|0 t|| ||t| | |||Q| j} tjd | | S#t$r} t|||| | d} ~ wwxYw) aPCreate the key for a value within a cache. This key is generated from the function's arguments. All arguments will be hashed, except for those named with a leading "_". Raises ------ StreamlitAPIException Raised (with a nicely-formatted explanation message) if we encounter an un-hashable arg. md5FusedforsecurityN_z'Not hashing %s because it starts with _hasherrX hash_source)rrXrTrz Cache key: %s)ranger_get_positional_arg_nameappenditemshashlibnew startswithr"debugrrr hexdigest)rXrSrrrT arg_pairsarg_idxarg_namekw_namekw_val args_hasher arg_valueexcr6s r/rrsC*/1IY(9+D':(Ig$6789',,., '6*+ ,++eU;K(S)  H$7$7$< MMCX N  S "%   "%%  S2%%'I MM/9-  # S&z49cR R Ss3C<< DDDctjdd}td|}t|j|j f||| t j|}t|||||jS#ttf$r7}tjd||jj}Yd}~`d}~wwxYw) zCreate the unique key for a function's cache. A function's key is stable across reruns of the app, and changes when the function's source code changes. rFrztypes.FunctionTyperzZFailed to retrieve function's source code when building its key; falling back to bytecode.)exc_infoN)rrr rrLrMinspect getsourceOSError TypeErrorr"r__code__co_coder)rXrS func_hasher source_coders r/rrs ++eU;K $d +D $++, ,''- KJD  "" Y ,  (  mm++ ,s A>>C -B??Cc>|dkryttj|jj }|t |k\ry||j tjjtjjfvr||jSy)zReturn the name of a function's positional argument. If arg_index is out of range, or refers to a parameter that is not a named positional argument (e.g. an *args, **kwargs, or keyword-only param), return None instead. rN) listr signature parametersvaluesrkind ParameterPOSITIONAL_OR_KEYWORDPOSITIONAL_ONLYr)rS arg_indexparamss r/rr s1}&*7+<+rsEH" #NNN'?.' I(>H%%cN CL5"GAJ5"p"WQT]"@ V&gadm&4VAVr@@ @@ @ % @  @F&#Rr1