o
    jZh3(                     @   s   d 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 e ZG dd dZG d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
    Npartial)Lock   )gateway_bootstrap)
gateway_io)get_execmodel)trace)
WorkerPool)XSpecc                   @   s   e Zd ZdZdZd&ddZedd Zed	d
 Zd'ddZ	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"d#Zd$d% ZdS )(GroupzGateway Groups.popen threadc                 C   sH   g | _ d| _t | _g | _| | |D ]}| | qt| j	 dS )zjinitialize group and make gateways as specified.
        execmodel can be 'thread' or 'eventlet'.
        r   N)
	_gateways_autoidcounterr   _autoidlock_gateways_to_joinset_execmodelmakegatewayatexitregister_cleanup_atexit)selfZxspecs	execmodelxspecr   r   D/var/www/html/lang_env/lib/python3.10/site-packages/execnet/multi.py__init__   s   
zGroup.__init__c                 C      | j S N)
_execmodelr   r   r   r   r   ,      zGroup.execmodelc                 C   r   r   )_remote_execmodelr!   r   r   r   remote_execmodel0   r"   zGroup.remote_execmodelNc                 C   s2   | j rtd|du r|}t|| _t|| _dS )as  Set the execution model for local and remote site.

        execmodel can be one of "thread" or "eventlet" (XXX gevent).
        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   r    r#   )r   r   r$   r   r   r   r   4   s   
zGroup.set_execmodelc                 C   s   dd | D }d| S )Nc                 S   s   g | ]}|j qS r   )id.0gwr   r   r   
<listcomp>I   s    z"Group.__repr__.<locals>.<listcomp>z
<Group %r>r   )r   Z
idgatewaysr   r   r   __repr__H   s   zGroup.__repr__c                 C   sB   t |tr
| j| S | jD ]}||ks|j|kr|  S qt|r   )
isinstanceintr   r&   KeyError)r   keyr)   r   r   r   __getitem__L   s   


zGroup.__getitem__c                 C   s$   z| |  W dS  t y   Y dS w )NTF)r.   r   r/   r   r   r   __contains__T   s   zGroup.__contains__c                 C   
   t | jS r   )lenr   r!   r   r   r   __len__[      
zGroup.__len__c                 C   s   t t| jS r   )iterlistr   r!   r   r   r   __iter__^   s   zGroup.__iter__c           
      C   sZ  |s| j }t|tst|}| | |jdu r| jj|_|jrD|jr%J | |j }|	t
}|t| t
|| j}t||}n9|jsM|jsM|jr\t
j|| jd}t||}n!|jruddlm} |j|| | jd}t||}ntd|j||_| | |js|js|jr|	d}|jrt|jpd}	||j|	|jf |  |S )ap  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', 'eventlet', 'gevent' model for execution
            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   )defaultspecr,   r   allocate_idr   r$   backendviasocketremote_execr   sendvarsZProxyIOr   Z	bootstrapr   sshZvagrant_sshZ	create_io r:   r%   _specspec	_registerchdirniceenvr-   	waitclose)
r   rF   ZmasterZproxy_channelZproxy_io_masterr)   ior:   channelrI   r   r   r   r   a   s@   







zGroup.makegatewayc                 C   sr   |j du r7| j% dt| j }|  jd7  _|| v r"td|||_ W d   dS 1 s0w   Y  dS dS )z4(re-entrant) allocate id for the given xspec object.Nr)   r   zalready have gateway with id )r&   r   strr   r%   )r   rF   r&   r   r   r   r<      s   
"zGroup.allocate_idc                 C   s<   t |drJ |jsJ |j| vsJ | j| | |_d S )N_group)hasattrr&   r   appendrO   r   gatewayr   r   r   rG      s
   

zGroup._registerc                 C   s   | j | | j| d S r   )r   remover   rQ   rR   r   r   r   _unregister   s   zGroup._unregisterc                 C   s    t d| d | jdd d S )Nz=== atexit cleanup z ===g      ?timeout)r	   	terminater!   r   r   r   r      s   zGroup._cleanup_atexitc                    s   | rDi }| D ]}|j jrd||j j< q| D ]}|j|vr |  qdd  dd t| j| fdd| jD  g | jdd< | sdS dS )	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.
        Tc                 S   s   |    | j  d S r   )join_iowaitr)   r   r   r   	join_wait   s   z"Group.terminate.<locals>.join_waitc                 S   s   t d|   | j  d S )Nz,Gateways did not come down after timeout: %r)r	   rZ   killr\   r   r   r   r^      s   zGroup.terminate.<locals>.killc                    s    g | ]}t  |t |fqS r   r   r'   r]   r^   r   r   r*      s    z#Group.terminate.<locals>.<listcomp>N)rF   r>   r&   exitsafe_terminater   r   )r   rW   Zviasr)   r   r_   r   rX      s*   
zGroup.terminatec                 K   s.   g }| D ]}| |j|fi | qt|S )zsremote_exec source on all member gateways and return
        MultiChannel connecting to all sub processes.
        )rQ   r@   MultiChannel)r   sourcekwargschannelsr)   r   r   r   r@      s   zGroup.remote_exec)r   r   r   )__name__
__module____qualname____doc__r;   r   propertyr   r$   r   r+   r0   r2   r5   r9   r   r<   rG   rU   r   rX   r@   r   r   r   r   r      s*    




C

#r   c                   @   sZ   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd ZdddZ	e
fddZdd ZdS )rb   c                 C   s
   || _ d S r   	_channels)r   re   r   r   r   r      r6   zMultiChannel.__init__c                 C   r3   r   )r4   rl   r!   r   r   r   r5      r6   zMultiChannel.__len__c                 C   r3   r   )r7   rl   r!   r   r   r   r9      r6   zMultiChannel.__iter__c                 C   s
   | j | S r   rk   r1   r   r   r   r0      r6   zMultiChannel.__getitem__c                 C   s
   || j v S r   rk   )r   Zchanr   r   r   r2      r6   zMultiChannel.__contains__c                 C   s   | j D ]}|| qd S r   )rl   rA   )r   itemchr   r   r   	send_each   s   
zMultiChannel.send_eachFc                 C   sH   t | drJ g }| jD ]}| }|r|||f q|| q|S )N_queue)rP   rl   ZreceiverQ   )r   Zwithchannellrn   objr   r   r   receive_each   s   
zMultiChannel.receive_eachc                    s   z j W S  ty?   d  _  jD ](} j d u r |jjj  _ |f fdd	}|tu r2|| q|j||d q j  Y S w )Nc                    s    j || f d S r   )rp   put)rr   rM   r!   r   r   putreceived  s   z4MultiChannel.make_receive_queue.<locals>.putreceived)	endmarker)	rp   AttributeErrorrl   rS   r   queueQueueNO_ENDMARKER_WANTEDZsetcallback)r   rv   rn   ru   r   r!   r   make_receive_queue	  s   


zMultiChannel.make_receive_queuec              	   C   sZ   d }| j D ]}z|  W q |jy   |d u rt }Y qw |r+|d |d d S )Nr      )rl   rK   ZRemoteErrorsysexc_infowith_traceback)r   firstrn   r   r   r   rK     s   
zMultiChannel.waitcloseN)F)rf   rg   rh   r   r5   r9   r0   r2   ro   rs   rz   r{   rK   r   r   r   r   rb      s    
rb   c                    sb   t |  fdd}g }|D ]\}}|||}|| q|D ]}|  q"j d d S )Nc                    s8    | }z	|j d W d S  ty   |  Y d S w )NrV   )spawngetOSError)termfunckillfuncZ	termreplyrW   Z
workerpoolr   r   termkill*  s   
z safe_terminate.<locals>.termkillrV   )r
   r   rQ   r   Zwaitall)r   rW   Zlist_of_paired_functionsr   Z	replylistr   r   Zreplyr   r   r   ra   '  s   
ra   )ri   r   r}   	functoolsr   	threadingr   rD   r   r   Zgateway_baser   r	   r
   r   r   objectrz   r   rb   ra   Zdefault_groupr   r   r   r   r   r   <module>   s&     V=
