
    V+                         d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ  G d de	      Z
 G d de	      Z G d de      Zdd	Z G d
 de      Z G d de	      Zy)    N)SSLErrorc                   .    e Zd ZdZd Zd Zd Zd Zd Zy)WINCHHandlerz?
    WINCH Signal handler to keep the PTY correctly sized.
    c                      || _         d| _        y)z
        Initialize a new WINCH handler for the given PTY.

        Initializing a handler has no immediate side-effects. The `start()`
        method must be invoked for the signals to be trapped.
        N)ptyoriginal_handler)selfr   s     //usr/lib/python3/dist-packages/dockerpty/pty.py__init__zWINCHHandler.__init__   s      $    c                 &    | j                          | S )z5
        Invoked on entering a `with` block.
        )startr	   s    r
   	__enter__zWINCHHandler.__enter__*   s    
 	

r   c                 $    | j                          y)z4
        Invoked on exiting a `with` block.
        N)stop)r	   _s     r
   __exit__zWINCHHandler.__exit__2   s    
 			r   c                 b      fd}t        j                   t         j                  |       _        y)z
        Start trapping WINCH signals and resizing the PTY.

        This method saves the previous WINCH handler so it can be restored on
        `stop()`.
        c                 b    | t         j                  k(  rj                  j                          y y N)signalSIGWINCHr   resize)signumframer	   s     r
   handlez"WINCHHandler.start.<locals>.handleA   s"    (! )r   N)r   r   r   )r	   r   s   ` r
   r   zWINCHHandler.start9   s!    	" !'foov Fr   c                 z    | j                   /t        j                  t        j                  | j                          yy)zU
        Stop trapping WINCH signals and restore the previous WINCH handler.
        N)r   r   r   r   s    r
   r   zWINCHHandler.stopG   s-    
   ,MM&//4+@+@A -r   N)	__name__
__module____qualname____doc__r   r   r   r   r    r   r
   r   r      s"    	%GBr   r   c                   $    e Zd Zd Zd Zd Zd Zy)	Operationc                     t               )z3
        are we dealing with a tty or not?
        NotImplementedErrorr	   kwargss     r
   israwzOperation.israwR        "##r   c                     t               )!
        start execution
        r'   r)   s     r
   r   zOperation.startX   r,   r   c                     t               )z0
        if we have terminal, resize it
        r'   r	   heightwidthr*   s       r
   r   zOperation.resize^   r,   r   c                     t               )zReturn sockets for streams.r'   r   s    r
   socketszOperation.socketsd   s    !##r   N)r   r    r!   r+   r   r   r4   r#   r   r
   r%   r%   P   s    $$$$r   r%   c                   8    e Zd ZdZd	dZd
dZd Zd Zd Zd Z	y)RunOperationz6
    class for handling `docker run`-like command
    Nc                    |t        j                  dt               d}|| _        || _        d| _        || _        |xs t        j                  | _        |xs t        j                  | _	        |xs t        j                  | _
        || _        y)Y
        Initialize the PTY using the docker.Client instance and container dict.
        NzThe default behaviour of dockerpty is changing. Please add logs=1 to your dockerpty.start call to maintain existing behaviour. See https://github.com/d11wtq/dockerpty/issues/51 for details.   )warningswarnDeprecationWarningclient	containerrawinteractivesysstdoutstderrstdinlogs)r	   r=   r>   r@   rB   rC   rD   rE   s           r
   r   zRunOperation.__init__n   s|    
 <MM  Z  \n  oD"&*

*

'cii
	r   c                 p   |xs | j                         \  }}}g }|rP| j                  rD|j                  t        j                  t        j
                  | j                        |d             |rD|j                  t        j                  |t        j
                  | j                        d             |rD|j                  t        j                  |t        j
                  | j                        d             | j                         d   d   s' | j                  j                  | j                  fi | |S )z
        Present the PTY of the container inside the current process.

        This will take over the current process' TTY until the container's PTY
        is closed.
        Fwait_for_outputpropagate_closeStateRunning)r4   r@   appendioPumpStreamrD   rB   rC   _container_infor=   r   r>   )r	   r4   r*   	pty_stdin
pty_stdout
pty_stderrpumpss          r
   r   zRunOperation.start   s     -4,Et||~)	:z))LL4::!6	SXYZLLRYYt{{-CUZ[\LLRYYt{{-CUZ[\##%g.y9DKKdnn77r   c                     | j                   9| j                         }| j                  j                         xr |d   d   | _         | j                   S )z
        Returns True if the PTY should operate in raw mode.

        If the container was not started with tty=True, this will return False.
        ConfigTty)r?   rQ   rB   isatty)r	   r*   infos      r
   r+   zRunOperation.israw   sG     88'')D{{))+EXu0EDHxxr   c                 J      j                          fd}t        |d      S )z
        Returns a tuple of sockets connected to the pty (stdin,stdout,stderr).

        If any of the sockets are not attached in the container, `None` is
        returned in the tuple.
        c           	      $   d   dj                  | j                                  rjj                  j                  j                  | ddddj
                  i      }t        j                  |      }d   d   r|S t        j                  |      S y )NrW   z	Attach{0}r9   streamrE   rX   )	format
capitalizer=   attach_socketr>   rE   rN   rP   Demuxer)keysocketr]   rZ   r	   s      r
   r`   z+RunOperation.sockets.<locals>.attach_socket   s    H~k001ABC22NN!Xq&$))< 6*>%(!M::f--r   )rD   rB   rC   )rQ   map)r	   r`   rZ   s   ` @r
   r4   zRunOperation.sockets   s(     ##%	 ="?@@r   c                 T    | j                   j                  | j                  ||       y)z-
        resize pty within container
        r1   r2   N)r=   r   r>   r0   s       r
   r   zRunOperation.resize   s!     	4>>&Fr   c                 L    | j                   j                  | j                        S )zA
        Thin wrapper around client.inspect_container().
        )r=   inspect_containerr>   r   s    r
   rQ   zRunOperation._container_info   s    
 {{,,T^^<<r   )TNNNNr   )
r   r    r!   r"   r   r   r+   r4   r   rQ   r#   r   r
   r6   r6   i   s'    $2A6G=r   r6   c                 0    | j                  ||||      }|S )N)ttyrD   )exec_create)r=   r>   commandr@   exec_ids        r
   rk   rk      s       GK XGNr   c                   >    e Zd ZdZd
dZddZd Zd Zd Zd Z	d	 Z
y)ExecOperationz7
    class for handling `docker exec`-like command
    Nc                     || _         || _        d | _        || _        |xs t        j
                  | _        |xs t        j                  | _        |xs t        j                  | _        d | _        y r   )	rm   r=   r?   r@   rA   rB   rC   rD   _info)r	   r=   rm   r@   rB   rC   rD   s          r
   r   zExecOperation.__init__   sV    &*

*

'cii

r   c                 Z   |xs | j                         }g }| j                  rD|j                  t        j                  t        j
                  | j                        |d             |j                  t        j                  |t        j
                  | j                        d             |S )r.   FrG   rI   )r4   r@   rM   rN   rO   rP   rD   rB   )r	   r4   r*   r]   rU   s        r
   r   zExecOperation.start   sv     *DLLNLL4::!6PUVWRWWVRYYt{{%;UST
 r   c                     | j                   1| j                  j                         xr | j                         | _         | j                   S )z
        Returns True if the PTY should operate in raw mode.

        If the exec was not started with tty=True, this will return False.
        )r?   rB   rY   is_process_ttyr)   s     r
   r+   zExecOperation.israw   s9     88{{))+E0C0C0EDHxxr   c                     | j                   j                  | j                  d| j                        }t	        j
                  |      }| j                         r|S t	        j                  |      S )zL
        Return a single socket which is processing all I/O to exec
        T)rc   rj   )r=   
exec_startrm   r@   rN   rP   rt   ra   )r	   rc   r]   s      r
   r4   zExecOperation.sockets   sW     ''TtGWGW'X6" M::f%%r   c                 T    | j                   j                  | j                  ||       y)z1
        resize pty of an execed process
        rf   N)r=   exec_resizerm   r0   s       r
   r   zExecOperation.resize  s!     	V5Ir   c                 .    | j                         d   d   S )z9
        does execed process have allocated tty?
        ProcessConfigrj   )
_exec_infor   s    r
   rt   zExecOperation.is_process_tty  s      1%88r   c                     | j                   *| j                  j                  | j                        | _         | j                   S )z<
        Caching wrapper around client.exec_inspect
        )rq   r=   exec_inspectrm   r   s    r
   r{   zExecOperation._exec_info  s2     ::11$,,?DJzzr   )TNNNr   )r   r    r!   r"   r   r   r+   r4   r   rt   r{   r#   r   r
   ro   ro      s+    "
	&J9r   ro   c                   2    e Zd ZdZd Zd ZddZddZd Zy)	PseudoTerminala!  
    Wraps the pseudo-TTY (PTY) allocated to a docker container.

    The PTY is managed via the current process' TTY until it is closed.

    Example:

        import docker
        from dockerpty import PseudoTerminal

        client = docker.Client()
        container = client.create_container(
            image='busybox:latest',
            stdin_open=True,
            tty=True,
            command='/bin/sh',
        )

        # hijacks the current tty until the pty is closed
        PseudoTerminal(client, container).start()

    Care is taken to ensure all file descriptors are restored on exit. For
    example, you can attach to a running container from within a Python REPL
    and when the container exits, the user will be returned to the Python REPL
    without adverse effects.
    c                      || _         || _        y)r8   N)r=   	operation)r	   r=   r   s      r
   r   zPseudoTerminal.__init__<  s    
 "r   c                 6    | j                   j                         S r   )r   r4   r   s    r
   r4   zPseudoTerminal.socketsD  s    ~~%%''r   Nc                    | j                   j                  |      }|D cg c]  }|j                  d       }}	 t        |       5  | j	                  |       d d d        |r+t        ||      D ]  \  }}t        j                  ||        y y c c}w # 1 sw Y   <xY w# |r+t        ||      D ]  \  }}t        j                  ||        w w xY w)N)r4   F)r   r   set_blockingr   _hijack_ttyziprN   )r	   r4   rU   pflagspumpflags          r
   r   zPseudoTerminal.startG  s    $$W$50561&66	0d# (  '( $'u$5 0LT4OOD$/0  7( ( $'u$5 0LT4OOD$/0 s(   BB  BB  BB   /Cc                     | j                   j                         sy|xs) t        j                  | j                   j                        }|$|\  }}	 | j                   j                  ||       yy# t        $ r Y yw xY w)z
        Resize the container's PTY.

        If `size` is not None, it must be a tuple of (height,width), otherwise
        it will be determined by the size of the current TTY.
        Nrf   )r   r+   rj   sizerB   r   IOError)r	   r   rowscolss       r
   r   zPseudoTerminal.resizeT  sx     ~~##%6sxx 5 56JD$%%T%>   s   A0 0	A<;A<c                    t        j                  | j                  j                  | j                  j	                               5  | j                          	 |D cg c]  }|j                  r| }}|D cg c])  }|j                  j                         s|j                  + }}t        j                  ||d      \  }}	 |D ]  }|j                           |D ]  }|j                           t        |D cg c]  }|j                          c}      rn	 	 d d d        y c c}w c c}w c c}w # t        $ r}	d|	j                   vr|	Y d }	~	8d }	~	ww xY w# 1 sw Y   y xY w)N)r?   <   )timeoutzThe operation did not complete)rj   Terminalr   rD   r+   r   eof	to_streamneeds_writerN   selectdo_writeflushallis_doner   strerror)
r	   rU   r   
read_pumpswrite_streams
read_readywrite_readywrite_streamr   es
             r
   r   zPseudoTerminal._hijack_ttyh  sA   \\$....DNN4H4H4JK 	 KKM).<Aaeea<
<6; Yq{{?V?V?X Y Y*,))JWY*Z'
K (3 0$--/0 !+ %

% 7AAIIK78 9  	  	  = Y 8    7qzzI J #	  	 sr   ED$,D$0E6D)D)$E7D39D.
D3E$
E.D33	E<EEEEE"r   )	r   r    r!   r"   r   r4   r   r   r   r#   r   r
   r   r      s     6#(0( r   r   )T)rA   r   r:   sslr   dockerpty.iorN   dockerpty.ttyrj   objectr   r%   r6   rk   ro   r   r#   r   r
   <module>r      se   "      3B6 3Bl$ $2c=9 c=L
II IX\ V \ r   