ó
S\c           @@ sˆ  d  Z  d d l m Z m Z d d l Z e j d d k  rD e Z n d „  Z e Z	 d d l
 m Z d d l Z d d l Z d d l Z d d l Z y d d l m Z Wn! e k
 rÊ d d l m Z n Xd d	 l m Z d d
 l m Z d Z d Z d e f d „  ƒ  YZ d „  Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e  f d „  ƒ  YZ! d e f d „  ƒ  YZ" d e f d „  ƒ  YZ# d S(   sM   Terminal management for exposing terminals to a web interface using Tornado.
i    (   t   absolute_importt   print_functionNi   c         C@ s   |  S(   N(    (   t   x(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   <lambda>   t    (   t   deque(   t   PtyProcessUnicode(   t
   PtyProcess(   t   gen(   t   IOLoopt   PYXTERM_t   xtermt   PtyWithClientsc           B@ sM   e  Z d  „  Z d „  Z e j d „ Z e j d „ Z e j	 e
 d „ ƒ Z RS(   c         C@ s+   | |  _  g  |  _ t g  d d ƒ|  _ d  S(   Nt   maxleni
   (   t   ptyproct   clientsR   t   read_buffer(   t   selfR   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   __init__#   s    		c         C@ sÒ   d } } xb |  j  D]W } | j \ } } | d k	 rJ | | k  rJ | } n  | d k	 r | | k  r | } q q W| d k s‡ | d k r‹ d S|  j j ƒ  \ } } | | f | | f k rÎ |  j j | | ƒ n  d S(   s  Set the terminal size to that of the smallest client dimensions.
        
        A terminal not using the full space available is much nicer than a
        terminal trying to use more than the available space, so we keep it 
        sized to the smallest client.
        i'  N(   R   t   sizet   NoneR   t
   getwinsizet
   setwinsize(   R   t   minrowst   mincolst   clientt   rowst   cols(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   resize_to_smallest+   s    
	c         C@ s   |  j  j | ƒ d S(   s'   Send a signal to the process in the ptyN(   R   t   kill(   R   t   sig(    (    s3   lib/python2.7/site-packages/terminado/management.pyR   A   s    c         C@ sH   t  j d k r |  j j | ƒ St  j |  j j ƒ } t  j | | ƒ d S(   s<   Send a signal to the process group of the process in the ptyt   ntN(   t   ost   nameR   R   t   getpgidt   pidt   killpg(   R   R   t   pgid(    (    s3   lib/python2.7/site-packages/terminado/management.pyR$   E   s    c         #@ sy  t  j d k r$ t j t j g } n t j t j t j t j g } t j ƒ  } ‡  f d †  } ˆ  j	 j
 ƒ  s~ t j t ƒ ‚ n  y« xD | D]< } ˆ  j | ƒ | ƒ  Vˆ  j	 j
 ƒ  sˆ t j t ƒ ‚ qˆ qˆ W| rˆ  j t j ƒ | ƒ  Vˆ  j	 j
 ƒ  st j t ƒ ‚ qt j t ƒ ‚ n  t j t ƒ ‚ WnI t k
 rt| ƒ  Vˆ  j	 j
 ƒ  sbt j t ƒ ‚ qut j t ƒ ‚ n Xd S(   sÿ   This forces a child process to terminate. It starts nicely with
        SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
        returns True if the child was terminated. This returns False if the
        child could not be terminated. R   c           @ s   t  j ˆ  j j ƒ S(   N(   R   t   sleepR   t   delayafterterminate(    (   R   (    s3   lib/python2.7/site-packages/terminado/management.pyR   Y   R   N(   R    R!   t   signalt   SIGINTt   SIGTERMt   SIGHUPt   SIGCONTR	   t   currentR   t   isaliveR   t   Returnt   TrueR   t   SIGKILLt   Falset   OSError(   R   t   forcet   signalst   loopR&   R   (    (   R   s3   lib/python2.7/site-packages/terminado/management.pyt	   terminateL   s4    (   t   __name__t
   __module__R   R   R(   R*   R   R$   R   t	   coroutineR2   R7   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyR   "   s   		c         C@ sJ   xC | j  ƒ  D]5 \ } } | d k r8 |  j | d ƒ q | |  | <q Wd S(   sA   Like dict.update(), but remove keys where the value is None.
    N(   t   itemsR   t   pop(   t   targett   changest   kt   v(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   _update_removingv   s    t   TermManagerBasec           B@ s˜   e  Z d  Z d i  d d d „ Z d d d d d „ Z d „  Z d „  Z d	 „  Z d d
 „ Z	 d d „ Z
 d „  Z e j d „  ƒ Z e j d „  ƒ Z RS(   s"   Base class for a terminal manager.R   c         C@ s|   | |  _  | |  _ | |  _ | |  _ t j t ƒ |  _ i  |  _ | d  k	 rW | |  _
 n! d d  l } | j
 j j ƒ  |  _
 d  S(   Ni    (   t   shell_commandt
   server_urlt   term_settingst	   extra_envt   loggingt	   getLoggerR8   t   logt
   ptys_by_fdR   t   ioloopt   tornado.ioloopR	   t   instance(   R   RC   RD   RE   RF   RK   t   tornado(    (    s3   lib/python2.7/site-packages/terminado/management.pyR      s    					i   iP   i    c         K@ sÆ   t  j j ƒ  } |  j j d t ƒ | d <d | | f } | r[ | r[ | d | | f 7} n  | | t d <t | ƒ | d <t | ƒ | d <|  j r¦ |  j | t d <n  |  j	 rÂ t
 | |  j	 ƒ n  | S(	   s@   Build the environment variables for the process in the terminal.t   typet   TERMs   %dx%ds   ;%dx%dt
   DIMENSIONSt   COLUMNSt   LINESt   URL(   R    t   environt   copyRE   t   gett   DEFAULT_TERM_TYPEt
   ENV_PREFIXt   strRD   RF   RA   (   R   t   heightt   widtht	   winheightt   winwidtht   kwargst   envt
   dimensions(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   make_term_env‘   s    		c         K@ ss   |  j  j ƒ  } |  j | d <| j | ƒ | d } |  j |   } t j | d | d | j d d ƒ ƒ} t	 | ƒ S(   s?   Make a new terminal, return a :class:`PtyWithClients` instance.RC   R`   t   cwdN(
   RE   RV   RC   t   updateRb   R   t   spawnRW   R   R   (   R   R_   t   optionst   argvR`   t   pty(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   new_terminal¤   s    
'c         C@ s<   | j  j } | |  j | <|  j j | |  j |  j j ƒ d S(   sB   Connect a terminal to the tornado event loop to read data from it.N(   R   t   fdRJ   RK   t   add_handlert   pty_readt   READ(   R   t   ptywclientsRj   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   start_reading®   s    c         C@ sJ   | j  j } |  j j d | ƒ |  j | =|  j j | ƒ | j  j ƒ  d S(   s(   Called when the pty has closed.
        s   EOF on FD %d; stopping readingN(   R   Rj   RI   t   infoRJ   RK   t   remove_handlert   close(   R   Rn   Rj   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   on_eof´   s
    
c         C@ s—   |  j  | } yG | j j d ƒ } | j j | ƒ x | j D] } | j | ƒ q< WWn< t k
 r’ |  j | ƒ x | j D] } | j	 ƒ  q{ Wn Xd S(   s>   Called by the event loop when there is pty data ready to read.i   N(
   RJ   R   t   readR   t   appendR   t   on_pty_readt   EOFErrorRs   t   on_pty_died(   R   Rj   t   eventsRn   t   sR   (    (    s3   lib/python2.7/site-packages/terminado/management.pyRl   À   s    c         C@ s
   t  ‚ d S(   s?  Override in a subclass to give a terminal to a new websocket connection
        
        The :class:`TermSocket` handler works with zero or one URL components
        (capturing groups in the URL spec regex). If it receives one, it is
        passed as the ``url_component`` parameter; otherwise, this is None.
        N(   t   NotImplementedError(   R   t   url_component(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   get_terminalÍ   s    c         C@ s   d S(   sF   Override this to e.g. kill terminals on client disconnection.
        N(    (   R   t	   websocket(    (    s3   lib/python2.7/site-packages/terminado/management.pyt   client_disconnectedÖ   s    c         c@ s   |  j  ƒ  Vd  S(   N(   t   kill_all(   R   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   shutdownÛ   s    c         c@ sS   g  } x0 |  j  j ƒ  D] } | j | j d t ƒ ƒ q Wx | D] } | Vq@ Wd  S(   NR4   (   RJ   t   valuesRu   R7   R0   (   R   t   futurest   termt   f(    (    s3   lib/python2.7/site-packages/terminado/management.pyR€   ß   s
    N(   R8   R9   t   __doc__R   R   Rb   Ri   Ro   Rs   Rl   R}   R   R   R:   R   R€   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyRB      s   	
				t   SingleTermManagerc           B@ s5   e  Z d  Z d „  Z d d „ Z e j d „  ƒ Z RS(   s9   All connections to the websocket share a common terminal.c         K@ s#   t  t |  ƒ j |   d  |  _ d  S(   N(   t   superR‡   R   R   t   terminal(   R   R_   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR   ë   s    c         C@ s8   |  j  d  k r1 |  j ƒ  |  _  |  j |  j  ƒ n  |  j  S(   N(   R‰   R   Ri   Ro   (   R   R|   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR}   ï   s    c         c@ s!   t  t |  ƒ j ƒ  Vd  |  _ d  S(   N(   Rˆ   R‡   R€   R   R‰   (   R   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR€   õ   s    N(	   R8   R9   R†   R   R   R}   R   R:   R€   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyR‡   é   s   	t   MaxTerminalsReachedc           B@ s   e  Z d  „  Z d „  Z RS(   c         C@ s   | |  _  d  S(   N(   t   max_terminals(   R   R‹   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR   û   s    c         C@ s   d |  j  S(   Ns$   Cannot create more than %d terminals(   R‹   (   R   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   __str__þ   s    (   R8   R9   R   RŒ   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyRŠ   ú   s   	t   UniqueTermManagerc           B@ s/   e  Z d  Z d d „ Z d d „ Z d „  Z RS(   s-   Give each websocket a unique terminal to use.c         K@ s#   t  t |  ƒ j |   | |  _ d  S(   N(   Rˆ   R   R   R‹   (   R   R‹   R_   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR     s    c         C@ sP   |  j  r3 t |  j ƒ |  j  k r3 t |  j  ƒ ‚ n  |  j ƒ  } |  j | ƒ | S(   N(   R‹   t   lenRJ   RŠ   Ri   Ro   (   R   R|   R„   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR}     s
    !c         C@ si   |  j  j d ƒ | j re t j d k rO | j j ƒ  |  j | j j j ƒ d S| j j	 t
 j ƒ n  d S(   s-   Send terminal SIGHUP when client disconnects.s-   Websocket closed, sending SIGHUP to terminal.R   N(   RI   Rp   R‰   R    R!   R   Rl   R   Rj   R$   R(   R+   (   R   R~   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR     s    	N(   R8   R9   R†   R   R   R}   R   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyR     s   t   NamedTermManagerc           B@ sz   e  Z d  Z d
 d „ Z d „  Z d Z d „  Z d „  Z e	 j
 d „ Z e j e d „ ƒ Z d „  Z e j d	 „  ƒ Z RS(   sG   Share terminals between websockets connected to the same endpoint.
    c         K@ s,   t  t |  ƒ j |   | |  _ i  |  _ d  S(   N(   Rˆ   R   R   R‹   t	   terminals(   R   R‹   R_   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR     s    	c         C@ s¥   | d  k	 s t ‚ | |  j k r, |  j | S|  j r_ t |  j ƒ |  j k r_ t |  j ƒ ‚ n  |  j j d | ƒ |  j ƒ  } | | _	 | |  j | <|  j
 | ƒ | S(   Ns$   New terminal with specified name: %s(   R   t   AssertionErrorR   R‹   RŽ   RŠ   RI   Rp   Ri   t	   term_nameRo   (   R   R’   R„   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR}   $  s    !	s   %dc         C@ sA   x: t  j d d ƒ D]& } |  j | } | |  j k r | Sq Wd  S(   Nt   starti   (   t	   itertoolst   countt   name_templateR   (   R   t   nR!   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   _next_available_name7  s    c         C@ sX   |  j  ƒ  } |  j ƒ  } |  j j d | ƒ | | _ | |  j | <|  j | ƒ | | f S(   Ns$   New terminal with automatic name: %s(   R˜   Ri   RI   Rp   R’   R   Ro   (   R   R!   R„   (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   new_named_terminal=  s    	c         C@ s   |  j  | } | j | ƒ d  S(   N(   R   R   (   R   R!   R   R„   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR   F  s    c         c@ s"   |  j  | } | j d | ƒ Vd  S(   NR4   (   R   R7   (   R   R!   R4   R„   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR7   J  s    c         C@ sI   t  t |  ƒ j | ƒ | j } |  j j d | ƒ |  j j | d  ƒ d  S(   Ns   Terminal %s closed(	   Rˆ   R   Rs   R’   RI   Rp   R   R<   R   (   R   Rn   R!   (    (    s3   lib/python2.7/site-packages/terminado/management.pyRs   O  s    	c         c@ s!   t  t |  ƒ j ƒ  Vi  |  _ d  S(   N(   Rˆ   R   R€   R   (   R   (    (    s3   lib/python2.7/site-packages/terminado/management.pyR€   U  s    N(   R8   R9   R†   R   R   R}   R–   R˜   R™   R(   R*   R   R   R:   R2   R7   Rs   R€   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyR     s   					($   R†   t
   __future__R    R   t   syst   version_infot   ordt	   byte_codeRZ   t   unicodet   collectionsR   R”   RG   R    R(   t
   ptyprocessR   t   ImportErrort   winptyR   RN   R   RL   R	   RY   RX   t   objectR   RA   RB   R‡   t	   ExceptionRŠ   R   R   (    (    (    s3   lib/python2.7/site-packages/terminado/management.pyt   <module>   s4   		T		j