
    +j2                         d dl Z d dlZddlmZmZmZ ddlmZ ddlm	Z	  e j
        e          Zd Z G d d          Z G d	 d
          Z G d d          Z G d de          ZdS )    N   )asynchronous	is_dundershare)reload)
Translatorc                 z    t          | t          j                  r |             o  |             |i |n | |i |S N)
isinstanceweakref
WeakMethod)fargskwargss      Q/DATA/AppData/hermes/venv/lib/python3.11/site-packages/trame_server/controller.py
_safe_callr      sS     a+,,	 $T$V$$Q    c                       e Zd ZddZd ZdS )TriggerCounterr   c                     || _         d S r
   _count)selfinits     r   __init__zTriggerCounter.__init__   s    r   c                 0    | xj         dz  c_         | j         S )Nr   r   r   s    r   nextzTriggerCounter.next   s    q{r   N)r   )__name__
__module____qualname__r   r    r   r   r   r      s7               r   r   c                   p     e Zd ZdZd fd	Zd Zd Zd Zd Zd	 Z	 fd
Z
d ZddZd ZddZddZ xZS )
ControlleraY  Controller acts as a container for function proxies

    It allows functions to be passed around that are not yet defined,
    and can be defined or re-defined later. For example:

    >>> ctrl.trigger_name(fn)
    trigger__12

    >>> f = ctrl.hello_func  # function is currently undefined
    >>> ctrl.hello_func = lambda: print("Hello, world!")
    >>> f()
    Hello, world!

    >>> ctrl.hello_func = lambda: print("Hello again!")
    >>> f()
    Hello again!

    >>> ctrl.on_data_change.add(lambda: print("Update pipeline!"))
    >>> ctrl.on_data_change.add(lambda: print("Update view!"))
    >>> ctrl.on_data_change.add(lambda: print("Wow that is pretty cool!"))
    >>> ctrl.on_data_change()
    "Update pipeline!"
    "Wow that is pretty cool!"
    "Update view!"
    >>> ctrl.on_data_change.clear(set_only=True)  # add, remove, discard, clear
    NFc           	      P   t                                          d|           t                                          d|r|nt                                 t                                          dt          |di                      t                                          dt          |di                      t                                          dt          |dt	                                           t                                          dt          |di                      d S )N__trame_hot_reload___translator	_triggers_triggers_fn2name_triggers_name_id
_func_dict)super__setattr__r   r   r   )r   
translatorinternal
hot_reload	__class__s       r   r   zController.__init__8   s    2J???M+U::VVVKxb)I)IJJJx1Db!I!I	
 	
 	
 	x1DnFVFV!W!W	
 	
 	
 	L%,*K*KLLLLLr   c                 t                          d          s j                                       fd}|S )z
        Use as decorator `@server.trigger(name)` so the decorated function
        will be able to be called from the client by doing `click="trigger(name)"`.

        :param name: A name to use for that trigger
        :type name: str
        	trigger__c                 f    t                               d           | j        <   j        | <   | S )Nztrigger(%s))loggerinfor(   r)   funcnamer   s    r   register_triggerz,Controller.trigger.<locals>.register_triggerO   s5    KKt,,,#'DN4 +/D"4(Kr   )
startswithr'   translate_key)r   r9   r:   s   `` r   triggerzController.triggerD   sV     {++ 	8#11$77D	 	 	 	 	 	  r   c                     || j         v r| j         |         S d| j                                         } |                     |          |           |S )z
        Given a function this method will register a trigger and returned its name.
        If manually registered, the given name at the time will be returned.

        :return: The trigger name for that function
        :rtype: str
        r3   )r)   r*   r   r=   )r   fnr9   s      r   trigger_namezController.trigger_nameW   s]     ''')"--:416688::T2r   c                 6    | j                             |          S )z
        Given a trigger name get its attached function/method.

        :return: The trigger function for that name
        :rtype: function
        )r(   getr   r9   s     r   
trigger_fnzController.trigger_fnf   s     ~!!$'''r   c                 ,    |                      |          S r
   )__getattr__rC   s     r   __getitem__zController.__getitem__o   s    %%%r   c                 2    |                      ||           d S r
   )r-   )r   r9   values      r   __setitem__zController.__setitem__r   s    u%%%%%r   c                     t          |          r!t                                          |          S | j                            |          }|| j        vrt          | |          | j        |<   | j        |         S r
   )r   r,   rF   r'   r<   r+   ControllerFunction)r   r9   r1   s     r   rF   zController.__getattr__u   so    T?? 	-77&&t,,,--d33t&&$6tT$B$BDOD!t$$r   c                     || j         v s|t          j         v rd| d}t          |          | j                            |          }|| j        v r|| j        |         _        d S t          | ||          | j        |<   d S )N'zA' is a special attribute on Controller that cannot be re-assigned)__dict__r$   	NameErrorr'   r<   r+   r8   rL   )r   r9   r8   msgs       r   r-   zController.__setattr__   s     4=  DJ,?$?$?!D ! ! !  C.. --d334?"")-DOD!&&&$6tT4$H$HDOD!!!r   c                       fd}|S )a1  
        Use as decorator `@ctrl.add(name)` so the decorated function
        will be added to a given controller name

        :param name: Controller method name to be added to
        :type name: str

        .. code-block::

            ctrl = server.controller

            @ctr.add("on_server_ready")
            def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready.add(on_ready)

        You can also make sure when the method get registered we clear
        any previous content.

        .. code-block::

            ctrl = server.controller

            @ctr.add("on_server_ready", clear=True)
            def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready.clear()
            ctrl.on_server_ready.add(on_ready)

        c                 v    r                                                                        |            | S r
   )clearaddr8   rT   r9   r   s    r   register_ctrl_methodz,Controller.add.<locals>.register_ctrl_method   s<     #T
  """JNN4   Kr   r"   r   r9   rT   rW   s   ``` r   rU   zController.add   1    H	 	 	 	 	 	 	 $#r   c                       fd}|S )a  
        Use as decorator `@ctrl.once(name)` so the decorated function
        will be added to a given controller name and will only execute once.

        :param name: Controller method name to be added to
        :type name: str

        .. code-block::

            ctrl = server.controller

            @ctr.once("on_server_ready")
            def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready.once(on_ready)

        c                 >                                  |            | S r
   )oncer7   s    r   rW   z-Controller.once.<locals>.register_ctrl_method   s    JOOD!!!Kr   r"   )r   r9   rW   s   `` r   r\   zController.once   s*    *	 	 	 	 	 	 $#r   c                       fd}|S )aV  
        Use as decorator `@ctrl.add_task(name)` so the decorated function
        will be added to a given controller name

        :param name: Controller method name to be added to
        :type name: str

        .. code-block::

            ctrl = server.controller

            @ctr.add_task("on_server_ready")
            async def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready.add_task(on_ready)

        You can also make sure when the method get registered we clear
        any previous content.

        .. code-block::

            ctrl = server.controller

            @ctr.add_task("on_server_ready", clear=True)
            async def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready.clear()
            ctrl.on_server_ready.add_task(on_ready)

        c                 v    r                                                                        |            | S r
   )rT   add_taskrV   s    r   rW   z1Controller.add_task.<locals>.register_ctrl_method   s>     #T
  """J%%%Kr   r"   rX   s   ``` r   r_   zController.add_task   rY   r   c                       fd}|S )a)  
        Use as decorator `@ctrl.set(name)` so the decorated function
        will be added to a given controller name

        :param name: Controller method name to be set to
        :type name: str

        .. code-block::

            ctrl = server.controller

            @ctr.set("on_server_ready")
            def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready = on_ready

        You can also make sure when the method get registered we clear
        any previous content.

        .. code-block::

            ctrl = server.controller

            @ctr.set("on_server_ready", clear=True)
            def on_ready(**state):
                pass

            # or
            ctrl.on_server_ready.clear()
            ctrl.on_server_ready = on_ready

        c                 J    r                                           | <   | S r
   )rT   rV   s    r   rW   z,Controller.set.<locals>.register_ctrl_method(  s/     #T
  """DJKr   r"   rX   s   ``` r   setzController.set  rY   r   )NNFF)r   r    r!   __doc__r   r=   r@   rD   rG   rJ   rF   r-   rU   r\   r_   rb   __classcell__)r1   s   @r   r$   r$      s        6
M 
M 
M 
M 
M 
M     &  ( ( (& & && & &% % % % %I I I +$ +$ +$ +$Z$ $ $6+$ +$ +$ +$Z+$ +$ +$ +$ +$ +$ +$ +$r   r$   c                   p    e Zd ZdZddZd Zd Zd Zd Zd Z	d	 Z
d
 ZddZd ZddZed             ZdS )rL   a  Controller functions are callable function proxy objects

    Any calls are forwarded to the internal function, which may be
    undefined or dynamically changed. If a call is made when the
    internal function is undefined, a FunctionNotImplementedError is
    raised.
    Nc                     || _         || _        || _        t                      | _        t                      | _        t                      | _        d| _        d S )NF)
controllerr9   r8   rb   funcs
task_funcs
funcs_oncecan_be_empty)r   rh   r9   r8   s       r   r   zControllerFunction.__init__;  sH    $ 		UU
%%%%!r   c           
         | j         Jt          | j                  t          | j                  z   dk    r| j        rd S t          | j                  t          | j                  t          | j                  z   }| j        	                                 d }| j         3| j
        rt          | j                   }n| j         }t          |gR i }| j
        r"t          t          t          |                    }fd|D             }t          | j                  D ]7}|                    t          j        t          |gR i                      8| j         |S t          |          r|g|S t          | j                  r|S |S )Nr   c                 0    g | ]}t          |gR i S r"   )r   ).0r   r   r   s     r   
<listcomp>z/ControllerFunction.__call__.<locals>.<listcomp>^  s1    EEEa:a1$111&11EEEr   )r8   lenri   rj   rl   FunctionNotImplementedErrorr9   listrk   rT   r0   r   r   mapappendr   create_task)r   r   r   	copy_listresultr   resultstask_fns    ``     r   __call__zControllerFunction.__call__G  s   9TZ3t3G3G!G1!L!L  t-di888$$tDO'<'<<	 9  49%%I3D333F33F? 	5S3344I FEEEE9EEE DO,, 	 	GNN(G)Md)M)M)Mf)M)MNN   
 9Ny>> 	&%W%%t 	Nr   c                 :    | j                             |           dS )z
        Add function to the set of functions to be called when
        the current ControllerFunction is called.
        After first execution, the function will automatically be removed.

        :param func: Function to add
        N)rk   rU   r   r8   s     r   r\   zControllerFunction.onceo  s      	D!!!!!r   c                 :    | j                             |           dS )z
        Add function to the set of functions to be called when
        the current ControllerFunction is called.

        :param func: Function to add
        N)ri   rU   r}   s     r   rU   zControllerFunction.addy  s     	
tr   c                 :    | j                             |           dS )z
        Add task to the set of coroutine to be called when
        the current ControllerFunction is called.

        :param func: Function to add
        N)rj   rU   r}   s     r   r_   zControllerFunction.add_task  s      	D!!!!!r   c                     | j                             |           | j                            |           | j                            |           dS )z
        Discard function to the set of functions to be called when
        the current ControllerFunction is called.

        :param func: Function to discard
        N)ri   discardrk   rj   r}   s     r   r   zControllerFunction.discard  sL     	
4   %%%%%%%%r   c                 :    | j                             |           dS )z
        Remove function to the set of functions to be called when
        the current ControllerFunction is called.

        :param func: Function to remove
        N)ri   remover}   s     r   r   zControllerFunction.remove  s      	
$r   c                 :    | j                             |           dS )z
        Remove task function to the set of functions to be called when
        the current ControllerFunction is called.

        :param func: Function to remove
        N)rj   r   r}   s     r   remove_taskzControllerFunction.remove_task  s      	t$$$$$r   Fc                     |sd| _         | j                                         | j                                         | j                                         dS )z
        Clear all the functions registered to the current ControllerFunction.

        :param set_only: (default: False) If true only the "added" one will be removed.
        N)r8   ri   rT   rk   rj   )r   set_onlys     r   rT   zControllerFunction.clear  sU      	DI
r   c                 n    | j         dS t          | j                  t          | j                  z   dk    S )z
        Check if at least a function was registered to the current ControllerFunction.

        :return: True if either a function was set or added
        NTr   )r8   rq   ri   rj   r   s    r   existszControllerFunction.exists  s3     9 44:T_!5!5599r   Tc                     || _         | S )z
        Enable entry to be empty.
        Useful for events when you don't know if someone will be listening.

        :return: self so it can be used inline like a builder.
        )rl   )r   rI   s     r   enable_emptyzControllerFunction.enable_empty  s     "r   c                     | j         j        S r
   )rh   r&   r   s    r   r0   zControllerFunction.hot_reload  s    33r   r
   rc   )T)r   r    r!   rd   r   r{   r\   rU   r_   r   r   r   rT   r   r   propertyr0   r"   r   r   rL   rL   2  s         
" 
" 
" 
"& & &P" " "  " " "	& 	& 	&     % % %       : : :    4 4 X4 4 4r   rL   c                       e Zd ZdS )rr   N)r   r    r!   r"   r   r   rr   rr     s        Dr   rr   )loggingr   utilsr   r   r   utils.hot_reloadr   utils.namespacer   	getLoggerr   r5   r   r   r$   rL   	Exceptionrr   r"   r   r   <module>r      s8     1 1 1 1 1 1 1 1 1 1 $ $ $ $ $ $ ' ' ' ' ' '		8	$	$         S$ S$ S$ S$ S$ S$ S$ S$lY4 Y4 Y4 Y4 Y4 Y4 Y4 Y4x	 	 	 	 	) 	 	 	 	 	r   