
    gI                    \   d dl mZ d dlZd dl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mZmZmZmZmZ d dlmZmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZ d dlmZm Z  d dl!m"Z" d dl#m$Z$ erd dl%m&Z&  ededef         Z'eg ef   Z( G d de      Z) G d de)      Z*	 d$dddd	 	 	 	 	 	 	 	 	 d%dZ+edd	 	 	 	 	 d&d       Z,e	 d$dd	 	 	 	 	 d'd       Z, ed      	 d$dd	 	 	 	 	 d(d       Z,edd	 	 	 	 	 d&d        Z-e	 d$dd	 	 	 	 	 d'd!       Z- ed"      	 d$dd	 	 	 	 	 d(d#       Z-y))    )annotationsN)abstractmethod)deepcopy)wraps)TYPE_CHECKINGAnyCallableProtocolTypeVaroverload)make_deprecated_name_warningshow_deprecation_warning)handle_uncaught_app_exception)FragmentHandledExceptionFragmentStorageKeyError)
ForwardMsg)gather_metrics)RerunExceptionStopException)get_script_run_ctx)time_to_seconds)	timedeltaF.)boundc                  l    e Zd ZdZedd	d       Zed
d       Zedd       Zedd       Zedd       Z	y)FragmentStoragea  A key-value store for Fragments. Used to implement the @st.fragment decorator.

    We intentionally define this as its own protocol despite how generic it appears to
    be at first glance. The reason why is that, in any case where fragments aren't just
    stored as Python closures in memory, storing and retrieving Fragments will generally
    involve serializing and deserializing function bytecode, which is a tricky aspect
    to implementing FragmentStorages that won't generally appear with our other *Storage
    protocols.
    Nc                    t         )z]Remove all fragments saved in this FragmentStorage unless listed in
        new_fragment_ids.NotImplementedError)selfnew_fragment_idss     O/var/www/openai/venv/lib/python3.12/site-packages/streamlit/runtime/fragment.pyclearzFragmentStorage.clear=   s
     "!    c                    t         )z.Returns the stored fragment for the given key.r   r    keys     r"   getzFragmentStorage.getC   
     "!r$   c                    t         )z%Saves a fragment under the given key.r   r    r'   values      r"   setzFragmentStorage.setH   r)   r$   c                    t         )z3Delete the fragment corresponding to the given key.r   r&   s     r"   deletezFragmentStorage.deleteM   r)   r$   c                    t         )z@Return whether the given key is present in this FragmentStorage.r   r&   s     r"   containszFragmentStorage.containsR   r)   r$   Nr!   zset[str] | NonereturnNoner'   strr4   Fragmentr'   r7   r,   r8   r4   r5   r'   r7   r4   r5   r'   r7   r4   bool)
__name__
__module____qualname____doc__r   r#   r(   r-   r/   r1    r$   r"   r   r   0   sk     " "
 " " " " " " " "r$   r   c                  B    e Zd ZdZd	dZd
ddZddZddZddZddZ	y)MemoryFragmentStoragezA simple, memory-backed implementation of FragmentStorage.

    MemoryFragmentStorage is just a wrapper around a plain Python dict that complies with
    the FragmentStorage protocol.
    c                    i | _         y r2   
_fragments)r    s    r"   __init__zMemoryFragmentStorage.__init__d   s	    /1r$   Nc                    |
t               }t        | j                  j                               }|D ]  }||vs| j                  |=  y r2   )r-   listrF   keys)r    r!   fragment_idsfids       r"   r#   zMemoryFragmentStorage.cleari   sF    #"uDOO0023C**OOC(  r$   c                l    	 | j                   |   S # t        $ r}t        t        |            d }~ww xY wr2   rF   KeyErrorr   r7   r    r'   es      r"   r(   zMemoryFragmentStorage.gets   s5    	2??3'' 	2)#a&11	2s    	3.3c                "    || j                   |<   y r2   rE   r+   s      r"   r-   zMemoryFragmentStorage.sety   s    $r$   c                j    	 | j                   |= y # t        $ r}t        t        |            d }~ww xY wr2   rN   rP   s      r"   r/   zMemoryFragmentStorage.delete|   s2    	2$ 	2)#a&11	2s    	2-2c                    || j                   v S r2   rE   r&   s     r"   r1   zMemoryFragmentStorage.contains   s    doo%%r$   )r4   r5   r2   r3   r6   r9   r:   r;   )
r=   r>   r?   r@   rG   r#   r(   r-   r/   r1   rA   r$   r"   rC   rC   ]   s%    2
)2%2&r$   rC    F)	run_everyadditional_hash_infoshould_show_deprecation_warningc               .   | dfd}|S | t              fd       }t        j                  t              5  |j                  j                  j                         t        j                        |_        ddd       |S # 1 sw Y   |S xY w)a  Contains the actual fragment logic.

    This function should be used by our internal functions that use fragments
    under-the-hood, so that fragment metrics are not tracked for those elements
    (note that the @gather_metrics annotation is only on the publicly exposed function)
    Nc                    t        |       S )NfuncrV   )fragment)frV   s    r"   wrapperz_fragment.<locals>.wrapper   s    # r$   c            	        	
 ddl m t               }|y t        |j                        t        j                               t        j                  d      }|j                  j                   dj                   d   j                           j                                |j                         	|j                  
 	
f	d}|j                  j!                  	|       rFt#               }t%              |j&                  _        	|j&                  _        |j-                  |        |       S )Nr   )context_dg_stackmd5.c                 z  	 dd l } rt        t        ddd             t        d      }|J |j                  r*t        	      |_        j                  t        
             |j                  j                         |j                  }|_
        	 |j                  k7  r|j                        nt        j                         }d }|5  | j                         5  	 j!                         d   }|j"                  r|j"                  j$                  ng d d |_         i }	 d d d        |cd d d        ||_
        g |_        S # t(        t*        f$ r}|d }~wt,        $ r}t/        |       t1        |      d }~ww xY w# 1 sw Y   ]xY w# 1 sw Y   nxY w	 ||_
        g |_        y # ||_
        g |_        w xY w)Nr   experimental_fragmentr]   z
2025-01-01T)suppress_warningrd   )	streamlitr   r   r   fragment_ids_this_runr   cursorsr-   r!   addcurrent_fragment_idactive_script_hashrun_with_active_hash
contextlibnullcontext	containerr(   _cursor
delta_pathcurrent_fragment_delta_pathr   r   	Exceptionr   r   )stctxprev_fragment_idactive_hash_contextresult	active_dgrQ   argsra   cursors_snapshotdg_stack_snapshotfragment_idinitialized_active_script_hashkwargsnon_optional_funcrX   s          r"   wrapped_fragmentz1_fragment.<locals>.wrap.<locals>.wrapped_fragment   s   ".(0/"$ %d;C?"?(( ''78 $$X.?%@A   $$[1  #66&1C#05 69O9OO ,,-KL#//1 $
 (> )9(<(<(>r(BI $-#4#4 !* 1 1 < <%'!r	?#C;
 &7%G%GF (B "E )(H +;'24/' +)  $ #$G( >
 :!< #;1"==>1 ( )((H +;'24/ +;'24/sg   8F* FFAE&	F/	F* E?EE?$E::E??FF	FFF* *F:)$streamlit.delta_generator_singletonsra   r   r   rj   r(   hashlibnewupdater>   r?   _get_delta_path_strencode	hexdigestrm   fragment_storager-   r   r   
auto_rerunintervalr   enqueue)r|   r   rw   hr   msgra   r}   r~   r   r   rW   r   rV   rX   s   ``    @@@@@r"   wrapz_fragment.<locals>.wrap   s(   I ";#CKK0$%5%9%9%;<KK	 ++,A.?.L.L-MN_`bNcNwNwNyMz  |P  {Q  R  Y  Y  [	
 kkm *-)?)?&W	5 W	5r 	  .>?,C&5i&@CNN#)4CNN&KK  !!r$   )r^   r   r4   r   )	r   ro   suppressAttributeError__dict__r   inspect	signature__signature__)r\   rV   rW   rX   r_   r   r   s    ```  @r"   	_fragmentr      s     |	  
u" u"n 
		^	, 	.778$../@A	 
- K 
- Ks    A B

BrV   c                    y r2   rA   r[   s     r"   r]   r]   !      
 	r$   c                    y r2   rA   r[   s     r"   r]   r]   +      
 r$   r]   c                   t        | |      S )a  Decorator to turn a function into a fragment which can rerun independently    of the full app.

    When a user interacts with an input widget created inside a fragment,
    Streamlit only reruns the fragment instead of the full app. If
    ``run_every`` is set, Streamlit will also rerun the fragment at the
    specified interval while the session is active, even if the user is not
    interacting with your app.

    To trigger an app rerun from inside a fragment, call ``st.rerun()``
    directly. To trigger a fragment rerun from within itself, call
    ``st.rerun(scope="fragment")``. Any values from the fragment that need to
    be accessed from the wider app should generally be stored in Session State.

    When Streamlit element commands are called directly in a fragment, the
    elements are cleared and redrawn on each fragment rerun, just like all
    elements are redrawn on each app rerun. The rest of the app is persisted
    during a fragment rerun. When a fragment renders elements into externally
    created containers, the elements will not be cleared with each fragment
    rerun. Instead, elements will accumulate in those containers with each
    fragment rerun, until the next app rerun.

    Calling ``st.sidebar`` in a fragment is not supported. To write elements to
    the sidebar with a fragment, call your fragment function inside a
    ``with st.sidebar`` context manager.

    Fragment code can interact with Session State, imported modules, and
    other Streamlit elements created outside the fragment. Note that these
    interactions are additive across multiple fragment reruns. You are
    responsible for handling any side effects of that behavior.

    .. warning::

        - Fragments can only contain widgets in their main body. Fragments
          can't render widgets to externally created containers.

    Parameters
    ----------
    func: callable
        The function to turn into a fragment.

    run_every: int, float, timedelta, str, or None
        The time interval between automatic fragment reruns. This can be one of
        the following:

            - ``None`` (default).
            - An ``int`` or ``float`` specifying the interval in seconds.
            - A string specifying the time in a format supported by `Pandas'
              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)``.

        If ``run_every`` is ``None``, the fragment will only rerun from
        user-triggered events.

    Examples
    --------
    The following example demonstrates basic usage of
    ``@st.fragment``. As an analogy, "inflating balloons" is a slow process that happens
    outside of the fragment. "Releasing balloons" is a quick process that happens inside
    of the fragment.

    >>> import streamlit as st
    >>> import time
    >>>
    >>> @st.fragment
    >>> def release_the_balloons():
    >>>     st.button("Release the balloons", help="Fragment rerun")
    >>>     st.balloons()
    >>>
    >>> with st.spinner("Inflating balloons..."):
    >>>     time.sleep(5)
    >>> release_the_balloons()
    >>> st.button("Inflate more balloons", help="Full rerun")

    .. output::
        https://doc-fragment-balloons.streamlit.app/
        height: 220px

    This next example demonstrates how elements both inside and outside of a
    fragement update with each app or fragment rerun. In this app, clicking
    "Rerun full app" will increment both counters and update all values
    displayed in the app. In contrast, clicking "Rerun fragment" will only
    increment the counter within the fragment. In this case, the ``st.write``
    command inside the fragment will update the app's frontend, but the two
    ``st.write`` commands outside the fragment will not update the frontend.

    >>> import streamlit as st
    >>>
    >>> if "app_runs" not in st.session_state:
    >>>     st.session_state.app_runs = 0
    >>>     st.session_state.fragment_runs = 0
    >>>
    >>> @st.fragment
    >>> def my_fragment():
    >>>     st.session_state.fragment_runs += 1
    >>>     st.button("Rerun fragment")
    >>>     st.write(f"Fragment says it ran {st.session_state.fragment_runs} times.")
    >>>
    >>> st.session_state.app_runs += 1
    >>> my_fragment()
    >>> st.button("Rerun full app")
    >>> st.write(f"Full app says it ran {st.session_state.app_runs} times.")
    >>> st.write(f"Full app sees that fragment ran {st.session_state.fragment_runs} times.")

    .. output::
        https://doc-fragment.streamlit.app/
        height: 400px

    You can also trigger an app rerun from inside a fragment by calling
    ``st.rerun``.

    >>> import streamlit as st
    >>>
    >>> if "clicks" not in st.session_state:
    >>>     st.session_state.clicks = 0
    >>>
    >>> @st.fragment
    >>> def count_to_five():
    >>>     if st.button("Plus one!"):
    >>>         st.session_state.clicks += 1
    >>>         if st.session_state.clicks % 5 == 0:
    >>>             st.rerun()
    >>>     return
    >>>
    >>> count_to_five()
    >>> st.header(f"Multiples of five clicks: {st.session_state.clicks // 5}")
    >>>
    >>> if st.button("Check click count"):
    >>>     st.toast(f"## Total clicks: {st.session_state.clicks}")

    .. output::
        https://doc-fragment-rerun.streamlit.app/
        height: 400px

    r   r   r[   s     r"   r]   r]   3  s    ` TY//r$   c                    y r2   rA   r[   s     r"   rf   rf     r   r$   c                    y r2   rA   r[   s     r"   rf   rf     r   r$   rf   c                   t        | |d      S )zRDeprecated alias for @st.fragment. See the docstring for the decorator's new name.T)rV   rX   r   r[   s     r"   rf   rf     s     TYPTUUr$   r2   )
r\   F | NonerV   $int | float | timedelta | str | NonerW   r7   rX   r<   r4   Callable[[F], F] | F)r\   r   rV   r   r4   r   )r\   r5   rV   r   r4   zCallable[[F], F])r\   r   rV   r   r4   r   ).
__future__r   ro   r   r   abcr   copyr   	functoolsr   typingr   r   r	   r
   r   r   streamlit.deprecation_utilr   r   streamlit.error_utilr   streamlit.errorsr   r   streamlit.proto.ForwardMsg_pb2r   streamlit.runtime.metrics_utilr   /streamlit.runtime.scriptrunner_utils.exceptionsr   r   7streamlit.runtime.scriptrunner_utils.script_run_contextr   streamlit.time_utilr   datetimer   r   r8   r   rC   r   r]   rf   rA   r$   r"   <module>r      sP   #       L L ? N 5 9 W /" CxS)*BG%"h %"Z&&O &&T X 7; ",1X
X 4X 	X
 &*X Xv 
 7;
 4 	 
 
 7;
 4 	 
 
O0 7;O0
O0 4O0 	O0 O0d 
 7;
 4 	 
 
 7;
 4 	 
 '(V 7;V
V 4V 	V )Vr$   