
    i-                       S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSK	J
r
  SSK	Jr  SSK	Jr  SS	K	Jr  SS
K	Jr  SSK	Jr  SSK	Jr  SSK	Jr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  \
(       a  SSKJr  \" 5       r  " S S5      r! " S S5      r"      SS jr#\!" 5       r$\$RJ                  r%\$RL                  r&g)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                      \ rS rSrSrSr S     SS jjr\SS j5       r\SS j5       r	 S     SS jjr
SS	 jrSS
 jrSS jrSS jrSS jrSS S jjrS!S jrS"S jrS"S jrS#S jrSS$S jjr    S%S jrSrg)&Group&   zGateway Group.popenc                    / U l         SU l        [        5       U l        / U l        U R                  U5        U H  nU R                  U5        M     [        R                  " U R                  5        g)zlInitialize 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)selfxspecs	execmodelxspecs       L/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/execnet/multi.py__init__Group.__init__+   s_     )+602 	9%EU# ,,-    c                    U R                   $ N)
_execmodelr&   s    r*   r(   Group.execmodel@   s    r-   c                    U R                   $ r/   )_remote_execmodelr1   s    r*   remote_execmodelGroup.remote_execmodelD   s    %%%r-   Nc                    U R                   (       a  [        S5      eUc  Un[        U5      U l        [        U5      U l        g)a=  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   r0   r4   )r&   r(   r5   s      r*   r!   Group.set_execmodelH   sC     >>T  #('	2!./?!@r-   c                L    U  Vs/ s H  oR                   PM     nnSU-  $ s  snf )Nz
<Group %r>)id)r&   gw
idgatewayss      r*   __repr__Group.__repr__\   s(    &*+deed
+j(( ,s   !c                    [        U[        5      (       a  U R                  U   $ U R                   H  nX!:X  d  UR                  U:X  d  M  Us  $    [	        U5      er/   )
isinstanceintr   r;   KeyError)r&   keyr<   s      r*   __getitem__Group.__getitem__`   sL    c3>>#&&..ByBEESL	 ! smr-   c                .     X     g! [          a     gf = f)NTF)rC   r&   rD   s     r*   __contains__Group.__contains__h   s!    	I 		s    
c                ,    [        U R                  5      $ r/   )lenr   r1   s    r*   __len__Group.__len__o       4>>""r-   c                >    [        [        U R                  5      5      $ r/   )iterlistr   r1   s    r*   __iter__Group.__iter__r   s    D())r-   c                &   U(       d  U R                   n[        U[        5      (       d  [        U5      nU R                  U5        UR                  c  U R
                  R                  Ul        UR                  (       a  UR                  (       a   eXR                     nUR                  [        5      nUR                  [        U5      5        [        R                  " X0R                  5      n[        R                  " XA5      nOUR                   (       d"  UR"                  (       d  UR$                  (       a5  [        R&                  " XR                  S9n[        R                  " Xa5      nOaUR                  (       a7  SSKJn  UR'                  XU R                  S9n[        R                  " X5      nO[-        SUR.                  < 35      eXl        U R3                  U5        UR4                  (       d"  UR6                  (       d  UR8                  (       ay  UR                  S5      n	UR6                  =(       a    [;        UR6                  5      =(       d    Sn
U	R                  UR4                  XR8                  45        U	R=                  5         U$ )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.
)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   )defaultspecrA   r   allocate_idr(   r5   backendviasocketremote_execr   sendvarsProxyIOr   	bootstrapr   sshvagrant_ssh	create_io rV   r8   _specspec	_registerchdirniceenvrB   	waitclose)r&   rf   masterproxy_channelproxy_io_masterr<   iorV   siochannelri   s              r*   r"   Group.makegatewayu   s   * ##D$&&;D>>!!22::DN88{{"?((^F"..z:MtDz*(00OO",,_CBZZ488t'7'7%%dnnEB",,R6B[[( **4*PC",,S7B9$**HIIr::dhhnnG II0#dii.6QDLL$**dHH56	r-   c                    UR                   c]  U R                     S[        U R                  5      -   nU =R                  S-  sl        X ;   a  [	        SU< 35      eX!l         SSS5        gg! , (       d  f       g= f)z4(re-entrant) allocate id for the given xspec object.Nr<   r   zalready have gateway with id )r;   r   strr   r8   )r&   rf   r;   s      r*   rX   Group.allocate_id   sk    77?!!C 3 344##q(#:$'DRF%KLL "! !!s   AA,,
A:c                    [        US5      (       a   eUR                  (       d   eUR                  U ;  d   eU R                  R                  U5        Xl        g )N_group)hasattrr;   r   appendrw   r&   gateways     r*   rg   Group._register   sJ    7H----zzzzz%%%g&r-   c                p    U R                   R                  U5        U R                  R                  U5        g r/   )r   remover    ry   rz   s     r*   _unregisterGroup._unregister   s(    g&%%g.r-   c                B    [        SU < S35        U R                  SS9  g )Nz=== atexit cleanup z ===g      ?timeout)r   	terminater1   s    r*   r%   Group._cleanup_atexit   s"    #D8401s#r-   c                   U (       a  [        5       nU  HE  nUR                  R                  (       d  M   UR                  UR                  R                  5        MG     U  H%  nUR                  U;  d  M  UR                  5         M'     SS jnSS jn[        U R                  UU R                   Vs/ s H  n[        XC5      [        XS5      4PM     sn5        / U R                  SS& U (       a  M  ggs  snf )a  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.
c                X    U R                  5         U R                  R                  5         g r/   )join_iowaitr<   s    r*   	join_wait"Group.terminate.<locals>.join_wait   s    	r-   c                T    [        SU -  5        U R                  R                  5         g )Nz,Gateways did not come down after timeout: %r)r   r   killr   s    r*   r   Group.terminate.<locals>.kill   s    DrIJr-   N)r<   r   returnNone)
setrf   rZ   addr;   exitsafe_terminater(   r    r   )r&   r   viasr<   r   r   s         r*   r   Group.terminate   s      UD77;;;HHRWW[[)  55$GGI   #444 Y+WT->?4 )+D""1%3 d(s   1 C2c                r    / nU  H%  nUR                  UR                  " U40 UD65        M'     [        U5      $ )zdremote_exec source on all member gateways and return
a MultiChannel connecting to all sub processes.)ry   r\   MultiChannel)r&   sourcekwargschannelsr<   s        r*   r\   Group.remote_exec   s8     BOOBNN6<V<= H%%r-   )r   r   r0   r   r    r4   ) thread)r'   zIterable[XSpec | str | None]r(   rt   r   r   )r   r   r/   )r(   rt   r5   z
str | Noner   r   )r   rt   )rD   zint | str | Gatewayr   r   )rD   rt   r   boolr   rB   )r   zIterator[Gateway])rf   zXSpec | str | Noner   r   )rf   r   r   r   )r{   r   r   r   r   r   )r   float | Noner   r   )r   zCstr | types.FunctionType | Callable[..., object] | types.ModuleTyper   r   )__name__
__module____qualname____firstlineno____doc__rW   r+   propertyr(   r5   r!   r>   rE   rI   rM   rS   r"   rX   rg   r   r%   r   r\   __static_attributes__r   r-   r*   r   r   &   s    K KS.2.DG.	.*   & & >BAA0:A	A()#*BH/$#+J
&S
& 
	
&r-   r   c                      \ rS rSrSS jrSS jrSS jrSS jrSS jrSS jr	\
SSS jj5       r\
SS	 j5       r S   SS
 jjr\4SS jjrSS jrSrg)r   i  c                    Xl         g r/   	_channels)r&   r   s     r*   r+   MultiChannel.__init__  s    !r-   c                ,    [        U R                  5      $ r/   )rL   r   r1   s    r*   rM   MultiChannel.__len__  rO   r-   c                ,    [        U R                  5      $ r/   )rQ   r   r1   s    r*   rS   MultiChannel.__iter__  s    DNN##r-   c                     U R                   U   $ r/   r   rH   s     r*   rE   MultiChannel.__getitem__  s    ~~c""r-   c                    XR                   ;   $ r/   r   )r&   chans     r*   rI   MultiChannel.__contains__  s    ~~%%r-   c                L    U R                    H  nUR                  U5        M     g r/   )r   r]   )r&   itemchs      r*   	send_eachMultiChannel.send_each  s    ..BGGDM !r-   c                    g r/   r   r&   withchannels     r*   receive_eachMultiChannel.receive_each      r-   c                    g r/   r   r   s     r*   r   r     r   r-   c                    [        U S5      (       a   e/ nU R                   H?  nUR                  5       nU(       a  UR                  X445        M.  UR                  U5        MA     U$ )N_queue)rx   r   receivery   )r&   r   lr   objs        r*   r   r      sX     4****..B**,C"# ! r-   c                v  ^   T R                   $ ! [         a    S T l         T R                   Hy  nT R                   c3  UR                  R                  R
                  R                  5       T l         U4SU 4S jjjnU[        L a  UR                  U5        Mj  UR                  X1S9  M{     T R                   s $ f = f)Nc                >   > TR                   R                  X45        g r/   )r   put)r   rq   r&   s     r*   putreceived4MultiChannel.make_receive_queue.<locals>.putreceived6  s    KKOOWN3r-   )	endmarker)rq   r   r   r   )	r   AttributeErrorr   r{   r(   queueQueueNO_ENDMARKER_WANTEDsetcallback)r&   r   r   r   s   `   r*   make_receive_queueMultiChannel.make_receive_queue-  s    	;; 	DKnn;;&"$**"6"6"<"<"B"B"DDK8: 4 4  33NN;/NN;ND % ;;	s    B&B87B8c                    S nU R                    H  n UR                  5         M     U(       a  Ueg ! UR                   a  nUc  Un S nAM=   S nAMC  S nAff = fr/   )r   rk   RemoteError)r&   firstr   excs       r*   rk   MultiChannel.waitclose?  sW    ..B  ! K  >>  =E ! s   1AAA)r   r   N)r   zSequence[Channel]r   r   r   )r   zIterator[Channel])rD   rB   r   r   )r   r   r   r   )r   objectr   r   ).)r   zLiteral[False]r   z	list[Any])r   zLiteral[True]r   zlist[tuple[Channel, Any]])F)r   r   r   z%list[tuple[Channel, Any]] | list[Any])r   r   r   )r   r   r   r   r+   rM   rS   rE   rI   r   r   r   r   r   rk   r   r   r-   r*   r   r     sr    "#$#&     #(	. 6I $	r-   r   c                   ^^ [        U 5      mSUU4S jjn/ nU H(  u  pVTR                  X5U5      nUR                  U5        M*     U H  nUR                  5         M     TR	                  TS9  g )Nc                v   > TR                  U 5      n UR                  TS9  g ! [         a
    U" 5          g f = f)Nr   )spawngetOSError)termfunckillfunc	termreplyr   
workerpools      r*   termkill safe_terminate.<locals>.termkillP  s:    $$X.		MM'M* 	J	s   $ 88r   r   )r   r   ry   r   waitall)	r(   r   list_of_paired_functionsr   	replylistr   r   replyr   s	    `      @r*   r   r   K  ss     I&J  I6  X> 7 		 w'r-   )r(   r   r   r   r   r   )'r   
__future__r   r#   types	functoolsr   	threadingr   typingr   r   r   r	   r
   r   r   r   rd   r   r   gateway_baser   r   r   r   r   r)   r   r{   r   r   r   r   r   r   default_groupr"   r!   r   r-   r*   <module>r      s    #                ! # $ '    h [& [&|D DN((#/(	(* ''++r-   