
    i-                       d Z ddlm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 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 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 ddlmZ ddlmZ ddlmZ ddlmZ e
rddlmZ  e            Z  G d d          Z! G d d          Z"d#d"Z# e!            Z$e$j%        Z%e$j&        Z&dS )$zk
Managing Gateway Groups and interactions with multiple channels.

(c) 2008-2014, Holger Krekel and others
    )annotationsNpartial)Lock)TYPE_CHECKING)Any)Callable)Iterable)Iterator)Literal)Sequence)overload   )gateway_bootstrap)
gateway_io)Channel)	ExecModel)
WorkerPool)get_execmodel)trace)XSpec)Gatewayc                      e Zd ZdZdZ	 d.d/dZed0d            Zed0d            Z	 d1d2dZ	d3dZ
d4dZd5dZd6dZd7dZd1d8d Zd9d"Zd:d$Zd:d%Zd;d&Zd1d<d)Zd=d-ZdS )>GroupzGateway Group.popen threadxspecsIterable[XSpec | str | None]	execmodelstrreturnNonec                    g | _         d| _        t                      | _        g | _        |                     |           |D ]}|                     |           t          j        | j	                   dS )z|Initialize a group and make gateways as specified.

        execmodel can be one of the supported execution models.
        r   N)
	_gateways_autoidcounterr   _autoidlock_gateways_to_joinset_execmodelmakegatewayatexitregister_cleanup_atexit)selfr   r    xspecs       T/home/ubuntu/.hermes/hermes-agent/venv/lib/python3.11/site-packages/execnet/multi.py__init__zGroup.__init__+   s|     )+6602 	9%%% 	$ 	$EU####,-----    r   c                    | j         S N)
_execmodelr.   s    r0   r    zGroup.execmodel@   s
    r2   c                    | j         S r4   )_remote_execmodelr6   s    r0   remote_execmodelzGroup.remote_execmodelD   s    %%r2   Nr9   
str | Nonec                    | j         rt          d          ||}t          |          | _        t          |          | _        dS )ae  Set the execution model for local and remote site.

        execmodel can be one of the supported execution models.
        It determines the execution model for any newly created gateway.
        If remote_execmodel is not specified it takes on the value of execmodel.

        NOTE: Execution models can only be set before any gateway is created.
        zBcan not set execution models if gateways have been created alreadyN)r%   
ValueErrorr   r5   r8   )r.   r    r9   s      r0   r)   zGroup.set_execmodelH   sW     > 	T   #('	22!./?!@!@r2   c                $    d | D             }d|z  S )Nc                    g | ]	}|j         
S r   )id).0gws     r0   
<listcomp>z"Group.__repr__.<locals>.<listcomp>]   s    +++be+++r2   z
<Group %r>r   )r.   
idgatewayss     r0   __repr__zGroup.__repr__\   s     ++d+++
j((r2   keyint | str | Gatewayr   c                    t          |t                    r| j        |         S | j        D ]}||k    s|j        |k    r|c S t	          |          r4   )
isinstanceintr%   r?   KeyError)r.   rE   rA   s      r0   __getitem__zGroup.__getitem__`   s_    c3 	'>#&&. 	 	BSyyBESLL			 )smmr2   boolc                :    	 | |          dS # t           $ r Y dS w xY w)NTF)rJ   r.   rE   s     r0   __contains__zGroup.__contains__h   s7    	II4 	 	 	55	s    
rI   c                *    t          | j                  S r4   )lenr%   r6   s    r0   __len__zGroup.__len__o       4>"""r2   Iterator[Gateway]c                D    t          t          | j                            S r4   )iterlistr%   r6   s    r0   __iter__zGroup.__iter__r   s    D(()))r2   specXSpec | str | Nonec                8   |s| j         }t          |t                    st          |          }|                     |           |j        | j        j        |_        |j        r|j        rJ | |j                 }|	                    t                    }|                    t          |                     t          j        || j                  }t          j        ||          }n|j        s|j        s|j        r1t          j        || j                  }t          j        ||          }nW|j        r9ddlm} |                    || | j                  }t          j        ||          }nt-          d|j                  ||_        |                     |           |j        s|j        s|j        rh|	                    d          }	|j        rt;          |j                  pd}
|	                    |j        |
|j        f           |	                                 |S )a  Create and configure a gateway to a Python interpreter.

        The ``spec`` string encodes the target gateway type
        and configuration information. The general format is::

            key1=value1//key2=value2//...

        If you leave out the ``=value`` part a True value is assumed.
        Valid types: ``popen``, ``ssh=hostname``, ``socket=host:port``.
        Valid configuration::

            id=<string>     specifies the gateway id
            python=<path>   specifies which python interpreter to execute
            execmodel=model 'thread', 'main_thread_only', 'eventlet', 'gevent' execution model
            chdir=<path>    specifies to which directory to change
            nice=<path>     specifies process priority of new process
            env:NAME=value  specifies a remote environment variable setting.

        If no spec is given, self.defaultspec is used.
        N)r    r   )gateway_socketzno gateway type found for a  
                import os
                path, nice, env = channel.receive()
                if path:
                    if not os.path.exists(path):
                        os.mkdir(path)
                    os.chdir(path)
                if nice and hasattr(os, 'nice'):
                    os.nice(nice)
                if env:
                    for name, value in env.items():
                        os.environ[name] = value
            r   )defaultspecrH   r   allocate_idr    r9   backendviasocketremote_execr   sendvarsProxyIOr   	bootstrapr   sshvagrant_ssh	create_io r\   r<   _specrY   	_registerchdirniceenvrI   	waitclose)r.   rY   masterproxy_channelproxy_io_masterrA   ior\   siochannelrn   s              r0   r*   zGroup.makegatewayu   s   *  	$#D$&& 	;;D>!!2:DN8 	J{""?$(^F"..z::MtDzz***(0OOO",_dCCBBZ 		J48 		Jt'7 		J%ddnEEEB",R66BB[ 	J(((((( **4*PPC",S$77BBH$*HHIIIr: 	  	 dh 	 nn G I0#di..6QDLL$*dDH5666	r2   r   c                    |j         f| j        5  dt          | j                  z   }| xj        dz  c_        || v rt	          d|          ||_         ddd           dS # 1 swxY w Y   dS dS )z4(re-entrant) allocate id for the given xspec object.NrA   r   zalready have gateway with id )r?   r'   r!   r&   r<   )r.   rY   r?   s      r0   r^   zGroup.allocate_id   s    7?!  C 3444##q(##::$%KR%K%KLLL                  ?s   AA!!A%(A%gatewayc                    t          |d          rJ |j        sJ |j        | vsJ | j                            |           | |_        d S )N_group)hasattrr?   r%   appendrz   r.   rx   s     r0   rl   zGroup._register   sY    7H-----zzz%%%%g&&&r2   c                n    | j                             |           | j                            |           d S r4   )r%   remover(   r|   r}   s     r0   _unregisterzGroup._unregister   s5    g&&&%%g.....r2   c                X    t          d| d           |                     d           d S )Nz=== atexit cleanup z ===g      ?timeout)r   	terminater6   s    r0   r-   zGroup._cleanup_atexit   s6    0D000111s#####r2   r   float | Nonec                N   | rt                      }| D ]-}|j        j        r|                    |j        j                   .| D ]}|j        |vr|                                  d	dd	dt          | j        |fd| j        D                        g | j        dd<   | dS dS )
aB  Trigger exit of member gateways and wait for termination
        of member gateways and associated subprocesses.

        After waiting timeout seconds try to to kill local sub processes of
        popen- and ssh-gateways.

        Timeout defaults to None meaning open-ended waiting and no kill
        attempts.
        rA   r   r"   r#   c                `    |                                   | j                                         d S r4   )join_iowaitrA   s    r0   	join_waitz"Group.terminate.<locals>.join_wait   s"    			r2   c                \    t          d| z             | j                                         d S )Nz,Gateways did not come down after timeout: %r)r   r   killr   s    r0   r   zGroup.terminate.<locals>.kill   s)    DrIJJJr2   c                P    g | ]"}t          |          t          |          f#S r   r   )r@   rA   r   r   s     r0   rB   z#Group.terminate.<locals>.<listcomp>   sB        Y++WT2->->?  r2   N)rA   r   r"   r#   )	setrY   r`   addr?   exitsafe_terminater    r(   )r.   r   viasrA   r   r   s       @@r0   r   zGroup.terminate   s     	+ UUD * *7; *HHRW[)))  5$$GGIII           "4     )+D"111%3  	+ 	+ 	+ 	+ 	+r2   sourceCstr | types.FunctionType | Callable[..., object] | types.ModuleTypeMultiChannelc                p    g }| D ]#}|                      |j        |fi |           $t          |          S )zlremote_exec source on all member gateways and return
        a MultiChannel connecting to all sub processes.)r|   rb   r   )r.   r   kwargschannelsrA   s        r0   rb   zGroup.remote_exec   sO      	> 	>BOONBN6<<V<<====H%%%r2   )r   r   )r   r   r    r!   r"   r#   )r"   r   r4   )r    r!   r9   r:   r"   r#   )r"   r!   )rE   rF   r"   r   )rE   r!   r"   rL   r"   rI   )r"   rT   )rY   rZ   r"   r   )rY   r   r"   r#   )rx   r   r"   r#   r"   r#   )r   r   r"   r#   )r   r   r"   r   )__name__
__module____qualname____doc__r]   r1   propertyr    r9   r)   rD   rK   rO   rR   rX   r*   r^   rl   r   r-   r   rb   r   r2   r0   r   r   &   s       K KS. . . . .*    X & & & X& >BA A A A A() ) ) )      # # # #* * * *B B B B BH      / / / /$ $ $ $#+ #+ #+ #+ #+J
& 
& 
& 
& 
& 
&r2   r   c                      e Zd Zd"dZd#dZd$d	Zd%dZd&dZd'dZe	d(d)d            Z
e	d*d            Z
	 d+d,dZ
efd-dZd.d Zd!S )/r   r   Sequence[Channel]r"   r#   c                    || _         d S r4   	_channels)r.   r   s     r0   r1   zMultiChannel.__init__  s    !r2   rI   c                *    t          | j                  S r4   )rQ   r   r6   s    r0   rR   zMultiChannel.__len__  rS   r2   Iterator[Channel]c                *    t          | j                  S r4   )rV   r   r6   s    r0   rX   zMultiChannel.__iter__  s    DN###r2   rE   r   c                    | j         |         S r4   r   rN   s     r0   rK   zMultiChannel.__getitem__  s    ~c""r2   chanrL   c                    || j         v S r4   r   )r.   r   s     r0   rO   zMultiChannel.__contains__  s    t~%%r2   itemobjectc                D    | j         D ]}|                    |           d S r4   )r   rc   )r.   r   chs      r0   	send_eachzMultiChannel.send_each  s.    . 	 	BGGDMMMM	 	r2   .withchannelLiteral[False]	list[Any]c                    d S r4   r   r.   r   s     r0   receive_eachzMultiChannel.receive_each      r2   Literal[True]list[tuple[Channel, Any]]c                    d S r4   r   r   s     r0   r   zMultiChannel.receive_each  r   r2   F%list[tuple[Channel, Any]] | list[Any]c                    t          | d          rJ g }| j        D ]E}|                                }|r|                    ||f           0|                    |           F|S )N_queue)r{   r   receiver|   )r.   r   lr   objs        r0   r   zMultiChannel.receive_each   st     4*****. 	 	B**,,C "c####r2   	endmarkerc                >    	  j         S # t          $ r d  _          j        D ]o} j         (|j        j        j                                         _         |fd fd}|t          u r|                    |           X|                    ||           p j         cY S w xY w)Nrv   r   r"   r#   c                @    j                             || f           d S r4   )r   put)r   rv   r.   s     r0   putreceivedz4MultiChannel.make_receive_queue.<locals>.putreceived6  s!    KOOWcN33333r2   )r   )rv   r   r"   r#   )	r   AttributeErrorr   rx   r    queueQueueNO_ENDMARKER_WANTEDsetcallback)r.   r   r   r   s   `   r0   make_receive_queuezMultiChannel.make_receive_queue-  s    	; 	 	 	DKn 
E 
E;&"$*"6"<"B"B"D"DDK8: 4 4 4 4 4 4 4  333NN;////NN;)NDDDD;	s   
 BBBc                    d }| j         D ]2}	 |                                 # |j        $ r}||}Y d }~+d }~ww xY w|r|d S r4   )r   rp   RemoteError)r.   firstr   excs       r0   rp   zMultiChannel.waitclose?  su    . 	  	 B >      =E   	K	 	s   "
:5:N)r   r   r"   r#   r   )r"   r   )rE   rI   r"   r   )r   r   r"   rL   )r   r   r"   r#   ).)r   r   r"   r   )r   r   r"   r   )F)r   rL   r"   r   )r   r   r   )r   r   r   r1   rR   rX   rK   rO   r   r   r   r   r   rp   r   r2   r0   r   r     s"       " " " "# # # #$ $ $ $# # # #& & & &        X    X #(     6I     $	 	 	 	 	 	r2   r   r    r   r   r   r"   r#   c                    t          |           dfd}g }|D ]1\  }}                    |||          }|                    |           2|D ]}|                                                                d S )Nr"   r#   c                                         |           }	 |                               d S # t          $ r  |             Y d S w xY w)Nr   )spawngetOSError)termfunckillfunc	termreplyr   
workerpools      r0   termkillz safe_terminate.<locals>.termkillP  sa    $$X..		MM'M***** 	 	 	HJJJJJJ	s   0 AAr   r   )r   r   r|   r   waitall)	r    r   list_of_paired_functionsr   	replylistr   r   replyr   s	    `      @r0   r   r   K  s     I&&J       I6    (  8X>>  		w'''''r2   )r    r   r   r   r"   r#   )'r   
__future__r   r+   types	functoolsr   	threadingr   typingr   r   r	   r
   r   r   r   r   rj   r   r   gateway_baser   r   r   r   r   r/   r   rx   r   r   r   r   r   r   default_groupr*   r)   r   r2   r0   <module>r      s8    # " " " " "                                                                                 ! ! ! ! ! ! # # # # # # $ $ $ $ $ $ ' ' ' ' ' '             !       fhh [& [& [& [& [& [& [& [&|D D D D D D D DN( ( ( (* '+r2   