
    [iyj                       U d dl mZ d dlZd dlmZmZmZmZ d dl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 d dlmZ d d	lmZ erd d
lmZ eee   z  Zeeef   eeeef      z  ZdZde d<   dZ!de d<   ee!gZ"de d<    e#ee!g      Z$de d<   e	 G d d             Z%ddZ&e	 G d deeef                Z'ddZ(	 	 	 	 	 	 	 	 ddZ)	 	 	 	 ddZ*y)     )annotationsN)IterableIteratorMappingMutableMapping)	dataclassfield)TYPE_CHECKINGAnyFinalcast)parse)StreamlitAPIException!StreamlitQueryParamDictValueError)
ForwardMsg)get_script_run_ctx)SupportsKeysAndGetItemembedz
Final[str]EMBED_QUERY_PARAMembed_optionsEMBED_OPTIONS_QUERY_PARAMzFinal[list[str]]EMBED_QUERY_PARAMS_KEYSzFinal[frozenset[str]]PROTECTED_QUERY_PARAMSc                  :    e Zd ZU dZded<   ded<   ded<   ded<   y)WidgetBindingz<Represents a binding between a widget and a query parameter.str	widget_id	param_key
value_typescript_hashN)__name__
__module____qualname____doc____annotations__     u/var/www/html/userprofiledev.eatanceapp.com/venv/lib/python3.12/site-packages/streamlit/runtime/state/query_params.pyr   r   /   s    FNNOr'   r   c                   t        | t              r| d   n| }|xdk(  r+ |j                         }|dk(  ry|dk(  ryt        d|       xdk(  r 	 t	        |      S xd	k(  r t        |      S xd
k(  r |S xdk(  r t        | t              rt        |       S | gS xdk(  rE t        | t              rt        |       n| g}g }|D ]  }	 |j                  t        |              |S dk(  rDt        | t              rt        |       n| g}g }|D ]  }	 |j                  t	        |              |S 	 |S # t        $ r |cY S w xY w# t        $ r |j                  |       Y w xY w# t        $ r |j                  |       Y rw xY w)a  Convert URL param to Python value based on WidgetState value type.

    Parameters
    ----------
    value : str | list[str]
        The URL parameter value(s).
    value_type : str
        The WidgetState value type (e.g., "bool_value", "string_value").

    Returns
    -------
    Any
        The parsed Python value appropriate for the widget type.

    Raises
    ------
    ValueError
        If the value cannot be parsed for the given type.
    
bool_valuetrueTfalseFzInvalid boolean value: 	int_valuedouble_valuestring_valuestring_array_valuedouble_array_valueint_array_value)
isinstancelistlower
ValueErrorintfloatappend)valuer   val	lower_valpartsresult_doublepart
result_ints           r(   parse_url_paramrB   9   s   * "%.%)EC
		IF"G#6se<==3x :J!",UD"94;FwF! $.eT#:DKE/1M/!((t5 
 !  $.eT#:DKE*,J,%%c$i0 
 JC  
" " /!((./ " ,%%d+,s6   
D- D>E-D;:D;>EEE;:E;c                     e Zd ZU dZ ee      Zded<    ee      Zded<    ee      Z	ded<    ee      Z
ded	<   d&d
Zd'dZd(dZd(dZd)dZ	 d*	 	 	 	 	 d+dZd,dZd-dZd.dZd/dZd/dZd0dZ	 	 	 	 d1dZd2dZd3d4dZ	 	 	 	 	 	 	 	 	 	 d5dZd6dZd7dZd8dZd9dZd7dZd:dZ d/d Z!d;d!Z"d<d"Z#	 d=	 	 	 	 	 d>d$Z$	 	 d?	 	 	 	 	 	 	 d@d%Z%y#)AQueryParamszA lightweight wrapper of a dict that sends forwardMsgs when state changes.
    It stores str keys with str and List[str] values.

    Also manages widget bindings to query parameters for the bind="query-params" feature.
    )default_factorydict[str, list[str] | str]_query_paramszdict[str, WidgetBinding]_bindings_by_param_bindings_by_widgetzdict[str, list[str]]_initial_query_paramsc                :    t        d | j                  D              S )Nc              3  L   K   | ]  }|j                         t        vr|  y wN)r6   r   ).0keys     r(   	<genexpr>z'QueryParams.__iter__.<locals>.<genexpr>   s'      
)yy{"99 )s   "$)iterrG   selfs    r(   __iter__zQueryParams.__iter__   s"     
))
 
 	
r'   c                   |j                         t        v rt        t        |            	 | j                  |   }t        |t              rt        |      dk(  ry|d   S |S # t        $ r t        t        |            w xY w)zRetrieves a value for a given key in query parameters.
        Returns the last item in a list or an empty string if empty.
        If the key is not present, raise KeyError.
        r    r*   )r6   r   KeyErrormissing_key_error_messagerG   r4   r5   lenrS   rO   r;   s      r(   __getitem__zQueryParams.__getitem__   s    
 99;114S9::
	;&&s+E%&u:? Ry L 	;4S9::	;s   -A! A! A! !A?c                    | j                  |      rt        d| d      | j                  ||       | j                          y )N%Cannot directly set query parameter '=' - it is bound to a widget. Modify the widget value instead.)is_boundr   _set_item_internal_send_query_param_msgrZ   s      r(   __setitem__zQueryParams.__setitem__   sL    =='7u =L M  	U+""$r'   c                2    t        | j                  ||       y rM   )_set_item_in_dictrG   rZ   s      r(   r`   zQueryParams._set_item_internal   s    $,,c59r'   c                   |j                         t        v rt        t        |            | j	                  |      rt        d| d      	 | j                  |= | j                          y # t        $ r t        t        |            w xY w)Nz(Cannot directly delete query parameter 'r^   )r6   r   rW   rX   r_   r   rG   ra   rS   rO   s     r(   __delitem__zQueryParams.__delitem__   s    99;114S9::==':3% @L M 	;""3'&&( 	;4S9::	;s   A* *Bc               4   t        |d      rFt        |d      r:t        d|      }t        |j                               }|D cg c]	  }|||   f }}nt        |      }|D cg c]  \  }}|	 }	}}|	j	                  |j                                |	D ]"  }| j                  |      st        d| d       |D ]  \  }}
| j                  ||
        |j                         D ]  \  }}
| j                  ||
        | j                          y c c}w c c}}w )Nkeysr[   0SupportsKeysAndGetItem[str, str | Iterable[str]]r]   r^   )
hasattrr   r5   ri   extendr_   r   r`   itemsra   )rS   otherkwds
other_dictri   kother_as_listrO   _keys_to_updater;   s              r(   updatezQueryParams.update   s    5&!ge]&CPRWXJ
)*D9=>AaA/M> !KM -::M&#q#M:diik* "C}}S!+;C5 AP Q  " (JC##C/ (**,JC##C/ '""$- ? ;s   D#Dc                    || j                   vs|j                         t        v rg S | j                   |   }t        |t              r|S |gS rM   )rG   r6   r   r4   r5   rZ   s      r(   get_allzQueryParams.get_all   sI    d(((CIIK;R,RI""3'"5$/u<eW<r'   c                ~    t        | j                  D ch c]  }|j                         t        vr| c}      S c c}w rM   )rY   rG   r6   r   rf   s     r(   __len__zQueryParams.__len__   sF      ---C99;&== -
 	
s   :c                ,    t        | j                        S rM   )r   rG   rR   s    r(   __str__zQueryParams.__str__  s    4%%&&r'   c                    t               }|y t               }t        j                  | j                  d      |j
                  _        |j
                  j                  |_        |j                  |       y )NTdoseq)r   r   r   	urlencoderG   page_info_changedquery_stringenqueue)rS   ctxmsgs      r(   ra   z!QueryParams._send_query_param_msg  s]     ";l-2__d.
* 00==Cr'   c                    | j                   D cg c]  }| j                  |      s| }}|r%t        ddj                  d |D               d      | j	                  d       | j                          y c c}w )NzDCannot clear query parameters - the following are bound to widgets: z, c              3  2   K   | ]  }t        |        y wrM   )repr)rN   rq   s     r(   rP   z$QueryParams.clear.<locals>.<genexpr>  s     ;lT!Wls   zA. Modify the widget values instead, or remove the bind parameter.Tpreserve_embed)rG   r_   r   joinclear_with_no_forward_msgra   )rS   rO   bound_paramss      r(   clearzQueryParams.clear  s    '+'9'9P'9T]]3=O'9P'V99;l;;< =RS 
 	&&d&;""$ Qs
   A6A6c                t    | j                   D ci c]  }|j                         t        vr|| |     c}S c c}w rM   )rG   r6   r   rf   s     r(   to_dictzQueryParams.to_dict  sF     ))
)yy{"99 cN)
 	
 
s   #5c                    | j                   j                         }| j                  d       	 | j                  |       y # t        $ r	 || _          w xY w)NTr   )rG   copyr   ru   r   )rS   _dict	old_values      r(   	from_dictzQueryParams.from_dict'  sT    
 &&++-	&&d&;	KK$ 	!*D	s   A   Ac                "    || j                   |<   y rM   )rG   )rS   rO   r<   s      r(   set_with_no_forward_msgz#QueryParams.set_with_no_forward_msg5  s    "%3r'   c                    | j                   j                         D ci c]   \  }}|j                         t        v r|r||" c}}| _         y c c}}w rM   )rG   rm   r6   r   )rS   r   rO   r;   s       r(   r   z%QueryParams.clear_with_no_forward_msg8  sQ     #00668
8
Uyy{55. J8
 
s   %Ac           	     h   |j                         t        v rt        d| dt         dt         d      | j
                  j                  |      }|r5|j                  |k7  r&| j                  j                  |j                  d       t        ||||      }|| j
                  |<   || j                  |<   y)a  Register a widget binding to a query parameter.

        If another widget was previously bound to this param_key, its binding
        is replaced. The old widget's entry in _bindings_by_widget is cleaned up
        to prevent orphaned references.

        Parameters
        ----------
        param_key : str
            The query parameter key (same as the widget's user key).
        widget_id : str
            The unique widget ID.
        value_type : str
            The WidgetState value type (e.g., "bool_value", "string_value").
        script_hash : str
            The script hash for MPA support.

        Raises
        ------
        StreamlitAPIException
            If the parameter is protected (embed, embed_options).
        z)Cannot bind to reserved query parameter 'z'. 'z' and 'z:' are used internally for Streamlit's embed functionality.N)r   r   r   r    )r6   r   r   r   r   rH   getr   rI   popr   )rS   r   r   r   r    old_bindingbindings          r(   bind_widgetzQueryParams.bind_widget?  s    : ?? 66';I; G%&g.G-H IGH  --11)<;00I=$$(()>)>E!#	
 .5	*.5  +r'   c                    | j                   j                  |d      }|r'| j                  j                  |j                  d       yy)zRemove a widget binding.

        Parameters
        ----------
        widget_id : str
            The unique widget ID.
        N)rI   r   rH   r   )rS   r   r   s      r(   unbind_widgetzQueryParams.unbind_widgetq  s@     **..y$?##''(9(94@ r'   c                    || j                   v S )a  Check if a query parameter is bound to a widget.

        Note: This check is case-sensitive, meaning "Foo" and "foo" are treated
        as different parameters. This is intentional because Python keys are
        case-sensitive and users explicitly choose their parameter names via
        the widget's `key` argument. This differs from embed parameter checks
        which are case-insensitive for URL compatibility.

        Parameters
        ----------
        param_key : str
            The query parameter key (case-sensitive).

        Returns
        -------
        bool
            True if the parameter is bound to a widget.
        )rH   rS   r   s     r(   r_   zQueryParams.is_bound}  s    & D3333r'   c                8    | j                   j                  |      S )a  Get the binding for a query parameter.

        Parameters
        ----------
        param_key : str
            The query parameter key.

        Returns
        -------
        WidgetBinding | None
            The binding if found, None otherwise.
        )rH   r   r   s     r(   get_binding_for_paramz!QueryParams.get_binding_for_param  s     &&**955r'   c                8    | j                   j                  |      S )zGet the binding for a widget.

        Parameters
        ----------
        widget_id : str
            The unique widget ID.

        Returns
        -------
        WidgetBinding | None
            The binding if found, None otherwise.
        )rI   r   )rS   r   s     r(   get_binding_for_widgetz"QueryParams.get_binding_for_widget  s     ''++I66r'   c                \    || j                   v r| j                   |= | j                          yy)a  Remove a query parameter without protection checks.

        This is an internal method for use by SessionState when clearing
        invalid URL-seeded values. It bypasses the bound param protection
        since the binding system itself needs to clear these values.

        Parameters
        ----------
        param_key : str
            The query parameter key to remove.

        Returns
        -------
        bool
            True if the param was removed, False if it didn't exist.
        TF)rG   ra   r   s     r(   remove_paramzQueryParams.remove_param  s2    " ***""9-&&(r'   c                @    t        j                  |d      }|| _        y)zStore the initial query params from the URL for session state seeding.

        Parameters
        ----------
        query_string : str
            The URL query string (without the leading '?').
        Tkeep_blank_valuesN)r   parse_qsrJ   )rS   r   parseds      r(   set_initial_query_paramsz$QueryParams.set_initial_query_params  s     E%+"r'   c           	         | j                   j                         D ci c]  \  }}|t        |t              r|n|g c}}| _        yc c}}w )a  Set _initial_query_params from the current filtered _query_params.

        This is called after MPA page transitions where populate_from_query_string()
        has filtered out params bound to widgets on other pages. Using this ensures
        widget seeding only uses params that are valid for the current page, preventing
        stale values from previous pages from leaking through.
        N)rG   rm   r4   r5   rJ   )rS   rq   vs      r(   %set_initial_query_params_from_currentz1QueryParams.set_initial_query_params_from_current  sL     >B=O=O=U=U=W&
=WTQAJq$'qaS0=W&
" &
s    Ac                h    | j                   j                  |      }|yt        |      dk(  r|d   S |S )a`  Get the initial URL value for a query parameter.

        This is used for seeding session state on initial page load.

        Parameters
        ----------
        param_key : str
            The query parameter key.

        Returns
        -------
        str | list[str] | None
            The initial value(s) if present, None otherwise.
        N   r   )rJ   r   rY   )rS   r   valuess      r(   get_initial_valuezQueryParams.get_initial_value  s=     ++//	:>v;!!9r'   c                X   dd}|dv rst        |t        t        f      rD|D cg c]  }|dk(  r ||      n
t        |       c}| j                  |<   | j                          y|dk(  r ||      n
t        |      }nt        |      }|| j                  |<   | j                          yc c}w )a  Set a corrected value for a query parameter.

        This is called when URL auto-correction is needed (e.g., after clamping
        a value to min/max bounds). It updates both the internal query params
        and sends a forward message to update the frontend URL.

        Parameters
        ----------
        param_key : str
            The query parameter key.
        value : Any
            The corrected value to set.
        value_type : str
            The WidgetState value type (e.g., "double_value", "int_value").
        c                    t        | t              r7t        j                  |       r"| t	        |       k(  rt        t	        |             S t        |       S )zFormat a number, using integer format if value is a whole number.

            Examples: 5.0 -> "5", 5.5 -> "5.5", 5 -> "5"
            Handles special float values (NaN, Inf) by returning them as-is.
            )r4   r9   mathisfiniter8   r   )r   s    r(   format_numberz7QueryParams._set_corrected_value.<locals>.format_number  s:     !U#a(8Q#a&[3q6{"q6Mr'   >   r3   r2   r1   r2   N)r   r   returnr   )r4   r5   tupler   rG   ra   )rS   r   r;   r   r   r   	str_values          r(   _set_corrected_valuez QueryParams._set_corrected_value  s    "
	  
 

 %$/ #1" )36J(JM!$PSTUPVV"1""9- **, !55 e$Z  E
I(19%""$1s   B'Nc                ,   t        j                  |d      }| j                          g }|j                         D ]  \  }}| j                  j                  |      }d}|-|+|j                  |vr|j                  |j                         d}|sUt        |      dk(  r| j                  |d       wt        |      dk(  r| j                  ||d	          | j                  ||        |D ]  }	| j                  |	        |r| j                          yy)
a  Populate query params from a URL query string.

        Clears current params and repopulates from the URL. When valid_script_hashes
        is provided (for MPA page transitions), filters out params bound to other pages.

        Parameters
        ----------
        query_string : str
            The raw query string from the URL (e.g., "foo=bar&baz=qux").
        valid_script_hashes : set[str] | None
            If provided, only keep params that are:
            - Unbound (no widget binding)
            - Bound to a widget with script_hash in this set
            Params bound to other pages are filtered out.
            If None, all params are kept (no filtering).
        Tr   NFr   rV   )r<   r   r*   )r   r   r   rm   rH   r   r    r:   r   rY   r   r   ra   )
rS   r   valid_script_hashesparsed_query_paramsstale_widget_idsrO   r<   r   should_keepr   s
             r(   populate_from_query_stringz&QueryParams.populate_from_query_string-  s   * $nn\TR&&(&(+113HC--11#6GK $/'''/BB !''(9(9:#s8q=00"0=X]00#b'0B00c:) 4. *Iy) * &&( r'   c                   g }| j                   D ]>  }||v r|r$|r"|j                  |      }|r|j                  |vr.|j                  |       @ d}|D ]Y  }| j                   j                  |      }|r)|j                  }	|	| j
                  v r| j
                  |	= d}| j                  |       [ |r| j                          yy)a  Remove bindings and URL params for widgets that are no longer active.

        This cleans up query params for conditional widgets that have been unmounted.
        For fragment runs, widgets outside the running fragment(s) are preserved.

        Note: Page-based cleanup for MPA navigation is handled separately via
        populate_from_query_string() which is called before the script runs.

        Parameters
        ----------
        active_widget_ids : set[str]
            Set of widget IDs that are currently active/rendered.
        fragment_ids_this_run : list[str] | None
            List of fragment IDs being run, or None for full script runs.
        widget_metadata : dict[str, Any] | None
            Widget metadata dict to check fragment IDs.
        FTN)rI   r   fragment_idr:   r   rG   r   ra   )
rS   active_widget_idsfragment_ids_this_runwidget_metadatar   r   metadataparams_removedr   r   s
             r(   remove_stale_bindingsz!QueryParams.remove_stale_bindingse  s    . 11I-- %*..y9 4 4<Q Q##I. 2 )I..229=G#--	 2 22**95%)Ny) * &&( r'   )r   zIterator[str]rO   r   r   r   )rO   r   r;   str | Iterable[str]r   None)rO   r   r   r   )r&   )rn   \Iterable[tuple[str, str | Iterable[str]]] | SupportsKeysAndGetItem[str, str | Iterable[str]]ro   r   r   r   )rO   r   r   z	list[str])r   r8   )r   r   )r   r   )r   zdict[str, str])r   r   r   r   )rO   r   r<   zlist[str] | strr   r   )F)r   boolr   r   )
r   r   r   r   r   r   r    r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   WidgetBinding | None)r   r   r   r   )r   r   r   r   )r   r   r   zstr | list[str] | None)r   r   r;   r   r   r   r   r   rM   )r   r   r   zset[str] | Noner   r   )NN)r   zset[str]r   zlist[str] | Noner   zdict[str, Any] | Noner   r   )&r!   r"   r#   r$   r	   dictrG   r%   rH   rI   rJ   rT   r[   rb   r`   rg   ru   rw   ry   r{   ra   r   r   r   r   r   r   r   r_   r   r   r   r   r   r   r   r   r   r&   r'   r(   rD   rD      s    16d0KM-K 493N0N49$4O1O 382M/M
;(%:;$ >@'%;'%
 '% 
'%R=
'

%
; 
	&
0606 06 	06
 06 
06d
A4*67.	,
,5%t 046)6) -6) 
	6)v 3715	3)#3)  03) /	3)
 
3)r'   rD   c                    d|  dS )Nzst.query_params has no key "z".r&   )rO   s    r(   rX   rX     s    )#b11r'   c                   t        |t              rt        |      |j                         t        v rt        d      t        |t              r-t        |t              s|D cg c]  }t        |       c}| |<   yt        |      | |<   yc c}w )zSet an item in a dictionary.zVQuery param embed and embed_options (case-insensitive) cannot be set programmatically.N)r4   r   r   r6   r   r   r   r   )target_dictrO   r;   items       r(   rd   rd     s}     %/44
yy{--#d
 	

 %":eS+A278%$CI%8Cu:C 9s   !B	c           	     D   i }t        | d      r@t        | d      r4t        d|       } | j                         D ]  }| |   }t        |||        n| D ]  \  }}||v rt	        |t
              rt        |      ||   }t	        |t              s|g}t	        |t              r9t	        |t              s)|j                  |D cg c]  }t        |       c}       n|j                  t        |             |||<   t        |||        t        j                  |d      S c c}w )z5Convert query params into a URL-encoded query string.ri   r[   rj   Tr}   )rk   r   ri   rd   r4   r   r   r5   r   r   rl   r:   r   r   )query_paramsprocessed_paramsrO   r;   current_valr   s         r(   process_query_paramsr     s   
 46|V$})M>
  $$&C %E.U; ' 'JC&&eT*;C@@.s3!+t4#.-KeX.z%7M&&e'DedD	e'DE&&s5z2(3 %!"2C?# '& ??+488 (Es   =D
)r;   zstr | list[str]r   r   r   r   r   )r   rF   rO   r   r;   r   r   r   )r   r   r   r   )+
__future__r   r   collections.abcr   r   r   r   dataclassesr   r	   typingr
   r   r   r   urllibr   streamlit.errorsr   r   streamlit.proto.ForwardMsg_pb2r   7streamlit.runtime.scriptrunner_utils.script_run_contextr   	_typeshedr   r   QueryParamValuer   QueryParamsInputr   r%   r   r   	frozensetr   r   rB   rD   rX   rd   r   r&   r'   r(   <module>r      s7   #  G G ( 2 2  U 5 V0%3/08E#BV<W3XX  !( : '(7 : 7- )  1:121 - 
   HV S).c* S) S)l2&+&25&>Q&	&&"97"9 	"9r'   