
    e.                        d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
mZ ddlZddlmZ ddlmZ ddlmZmZ d	d
lmZ  G d dej                  Z G d de          ZdS )z
The Terminal Widget makes it easy to create Panel Applications with Terminals.

- For example apps which streams the output of processes or logs.
- For example apps which provide interactive bash, python or ipython terminals
    )annotationsN)ClassVarMapping)JupyterComm   )PeriodicCallback)edit_readonly	lazy_load   )Widgetc                      e Zd ZdZ ej        eefd          Z ej	        dd          Z
 ej        d          Z ej        d	dd
          Z ej        dd          Z ej        dd          Z ej        d          Z ej        ed          Z ej        dd          Z ej        dd	d          Z ej        d          Z ej        d          Z fdZed             Zd Zd Z ej        ddd          d             Z d  Z!d! Z"ed"             Z#d-d$Z$d% Z%d& Z& ej        d'd          d(             Z' ej        d)d          d*             Z(d.d,Z) xZ*S )/TerminalSubprocesszn
    The TerminalSubProcess is a utility class that makes running
    subprocesses via the Terminal easy.
    z
        The arguments used to run the subprocess. This may be a string
        or a list. The string cannot contain spaces. See subprocess.run
        docs for more details.)class_doczKills the running processTr   constantze
        Any other arguments to run the subprocess. See subprocess.run
        docs for more details.r   Fz2
        Whether or not the subprocess is running.)defaultr   r   r   zChild process idr   r   zChild file descriptor.i P  r   z*
        Watches the subprocess for output2   z#Period length of _periodic_callbackz;
        The Terminal to which the subprocess is connected.)r   
allow_refsr   z%Watches the subprocess for user inputc                J     t                      j        d|| j        d| d S )N)	_terminalkill )super__init___kill)selfterminalkwargs	__class__s      6lib/python3.11/site-packages/panel/widgets/terminal.pyr   zTerminalSubprocess.__init__A   s/    G8$*GGGGGGG    c                @    d                     d | D                       S )N c                6    g | ]}t          j        |          S r   )shlexquote).0cs     r$   
<listcomp>z-TerminalSubprocess._quote.<locals>.<listcomp>F   s     8881A888r%   )join)commands    r$   _quotezTerminalSubprocess._quoteD   s#    ww88888999r%   c                     t          |t                    r                     |          S t          |t                    r fd|D             S |S )Nc                :    g | ]}                     |          S r   )r0   )r+   argr    s     r$   r-   z2TerminalSubprocess._clean_args.<locals>.<listcomp>L   s%    555DKK$$555r%   )
isinstancestrr0   listr    argss   ` r$   _clean_argszTerminalSubprocess._clean_argsH   sX    dC   	%;;t$$$dD!! 	655555555r%   c                <   ddl }|s| j        }|st          d          | j        rt          d          |                     |          }| j        ri | j        |}|                                \  }}|dk    rh	 t          j        |fi |}t          t          |                     dS # t          $ r*}t          t          |          dz              Y d}~dS d}~ww xY w|| _        || _        |                                  t          | j        | j                  | _        | j                                         | j        j                            | j        dd	          | _        t+          j        |           5  d
| _        ddd           dS # 1 swxY w Y   dS )z,
        Runs a subprocess command.
        r   NzError. No args providedz@Error. A child process is already running. Cannot start another.z&
CompletedProcess('FileNotFoundError'))callbackperiodvalueF)onlychangedT)ptyr8   
ValueErrorrunningr9   r"   fork
subprocessrunprintr5   FileNotFoundError
_child_pid_fd_set_winsizer   &_forward_subprocess_output_to_terminal_period_periodic_callbackstartr   paramwatch%_forward_terminal_input_to_subprocess_watcheredit_constant)r    r8   r"   r?   	child_pidfdresultes           r$   rD   zTerminalSubprocess.runO   s+    	


  	9D 	86777< 	R   %%; 	/..v.F ((**B>>J#7777c&kk"""""$ J J Jc!ffHHIIIIIIIIIJ (DODH&6D|' ' 'D# #))+++ N066:G! 7  DM $T** $ $#$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $s*   :.B* *
C4CC<FFFz_terminal.ncolsz_terminal.nrowsrO   c                    | j         | j        j        r| j        j        sd S dd l}dd l}dd l}|                    d| j        j        | j        j        dd          }	 |                    | j         |j	        |           d S # t          $ r Y d S w xY w)Nr   HHHH)rH   r   nrowsncolsfcntlstructtermiospackioctl
TIOCSWINSZOSError)r    r\   r]   r^   winsizes        r$   rI   zTerminalSubprocess._set_winsize   s    84>#7t~?SF++fdn&:DN<PRSUVWW	KK'"4g>>>>> 	 	 	DD	s   !A? ?
BBc                   | j         }|                                  |rQt          j        t          j        |          t
          j                   | j                            d| d           d S | j                            d           d S )Nz
The process z was killed
z
No running process to kill
)	rG   _resetoskillpggetpgidsignalSIGTERMr   write)r    eventsrS   s      r$   r   zTerminalSubprocess._kill   s    O	 	CIbj++V^<<<N  !J)!J!J!JKKKKKN  !ABBBBBr%   c                .   d| _         d| _        | j        r | j                                         d | _        | j        r$| j        j                            | j                   t          j        |           5  d| _	        d d d            d S # 1 swxY w Y   d S )Nr   F)
rH   rG   rL   stoprQ   r   rN   unwatchrR   rA   r    s    r$   re   zTerminalSubprocess._reset   s    " 	+#((***&*D#= 	8N ((777 && 	! 	! DL	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	!s   5B

BBc                <    | d |                      d                   S NCompletedProcess)rfind)r=   s    r$   _remove_last_line_from_stringz0TerminalSubprocess._remove_last_line_from_string   s     6u{{#566677r%   r   c                    t          j        ||          }t          |dz             D ]A}	 |                    d          c S # t          $ r |t          j        |d          z   }Y >w xY wt          d          )zHUTF-8 characters can be multi-byte so need to decode on correct boundaryr   zutf-8z(Could not find decode boundary for UTF-8)rf   readrangedecodeUnicodeDecodeErrorUnicodeError)r    rT   max_read_bytesmax_extra_bytesdata_s         r$   _decode_utf8_on_boundaryz+TerminalSubprocess._decode_utf8_on_boundary   s    wr>**q()) 	- 	-A-{{7+++++% - - -bgb!nn,-EFFFs   A"A'&A'c                :   | j         sd S t          j        | j         gg g | j                  \  }}}|sd S |                     | j         | j                  }d|v r)|                                  |                     |          }| j                            |           d S rr   )	rH   select_timeout_secr   _max_read_bytesre   ru   r   rk   )r    
data_readyr   outputs       r$   rJ   z9TerminalSubprocess._forward_subprocess_output_to_terminal   s    x 	F#]DH:r2t?PQQQ 	F..tx9MNN ''KKMMM77??FV$$$$$r%   c                    | j         r8t          j        | j         | j        j                                                   d S d S N)rH   rf   rk   r   r=   encoder    rl   s     r$   rP   z8TerminalSubprocess._forward_terminal_input_to_subprocess   sA    8 	>HTXt~3::<<=====	> 	>r%   r8   c                    | j         }t          |t                    r,d|v r*t          d| d|                    d                     d S d S )N z
The args 'zV' provided contains spaces. They must instead be provided as the
                list )r8   r4   r5   r@   splitr7   s     r$   _validate_argsz!TerminalSubprocess._validate_args   sk    ydC   	SD[[*t * *jjoo* *  	 	[[r%   rK   c                :    | j         r| j        | j         _        d S d S r   )rL   rK   r<   rp   s    r$   _update_periodic_callbackz,TerminalSubprocess._update_periodic_callback   s*    " 	:-1\D#***	: 	:r%   Nc                (    d| j          d| j         dS )NzTerminalSubprocess(args=z
, running=))r8   rA   r    depths     r$   __repr__zTerminalSubprocess.__repr__   s    N$)NNt|NNNNr%   )r   r   )+__name__
__module____qualname____doc__rN   ClassSelectorr5   r6   r8   Actionr   Dictr"   BooleanrA   IntegerrG   rH   r   r   rL   rK   	Parameterr   r   rQ   r   staticmethodr0   r9   rD   dependsrI   r   re   ru   r   rJ   rP   r   r   r   __classcell__r#   s   @r$   r   r      s        
 5sDk 8" # # #D
 5<7$GGGDUZ " $ $ $F emED ?5 6 6 6G q.@AAAJ
%-'?
@
@
@C#emI666O,,4D K- . . . emB,QRRRG% F> ? ? ?I !5=+++Lu#JKKKHH H H H H : : \:  7$ 7$ 7$r U]$&7tDDD
 
 ED
C C C	! 	! 	! 8 8 \8G G G G% % %> > > U]6&&&  '& U]9D))): : *):O O O O O O O Or%   r   c                  H    e Zd ZU dZ ej        dd          Z ej        i dd          Z ej	        dd	
          Z
 ej        dd          Z ej        dd          Z ej	        ddd          Z ej        dd
          Z ej        d          Z ej	        d          ZdddddddZded<   d/ fd	Zd Zd0 fd	Zd Zd Z ej        d d!          d"             Zd/d#Zed$             Zed%             Zd& Z d' Z!d( Z"d) Z#d1d*Z$d1d+Z%d, Z&d- Z'd. Z( xZ)S )2Terminala  
    The `Terminal` widget renders a live terminal in the browser using
    the xterm.js library making it possible to display logs or even
    provide an interactive terminal in a Panel application.

    Reference: https://panel.holoviz.org/reference/widgets/Terminal.html

    :Example:

    >>> Terminal(
    ...     "Welcome to the Panel Terminal!", options={"cursorBlink": True}
    ... )
    zClears the Terminal.Tr   z
        Initial Options for the Terminal Constructor. cf.
        https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/)r   
precedencer   r'   z.
        System output written to the Terminalr   z/
        The number of columns in the terminal.)readonlyr   z,
        The number of rows in the terminal.InputzO
        User input received from the Terminal. Sent one character at the time.)labelr   r   Fz7
        Whether or not to write to the server console.z$Sends a signal to clear the terminalr   r   Nr   )clearnamer   _outputr=   write_to_consolez"ClassVar[Mapping[str, str | None]]_renamec                r    |pdx|d<   }| j         |d<    t                      j        dd|i| d | _        d S )Nr'   r   r   r   r   )_clearr   r   _subprocess)r    r   paramsr#   s      r$   r   zTerminal.__init__
  sQ    %+\r1yF+w111&111r%   c                $   |}t          |t                    r|}n:t          |t                    r|                    d          }nt          |          }| j        |k    rd| _        || _        | xj        |z  c_        t          | j                  S )Nutf8r'   )r4   r5   bytesry   r   r   len)r    _Terminal__scleaneds      r$   rk   zTerminal.write  s    c3 	GGU## 	jj((GG#hhG<7""DLw4;r%   c                    | j         *t          ddt          |t                    |          | _         t	                                          ||||          }| j        |_        |                     d|||           |S )Nzpanel.models.terminalr   	keystroke)modelr   comm)_widget_typer
   r4   r   r   
_get_modelr   _register_events)r    r   rootparentr   r   r#   s         r$   r   zTerminal._get_model!  s|    $ )'Zk5R5RTX! !D ""3fd;;{kCdKKKr%   c                    t          |           5  |j        | _        t          j        |           5  d| _        d d d            n# 1 swxY w Y   d d d            d S # 1 swxY w Y   d S )Nr'   )r	   keyr=   rN   discard_events)r    events     r$   _process_eventzTerminal._process_event+  s    4   	  	 DJ%d++    
                             	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	 s3   !AAAA			AA		AA!$A!c                4    d| _         | xj        dz  c_        dS )z4
        Clears all output on the terminal.
        r'   r   N)r   _clearsr   s     r$   r   zTerminal._clear1  s     r%   r   rW   c                `    | j         r&t          j                            | j                   d S d S r   )r   sys
__stdout__rk   r   rp   s    r$   _writezTerminal._write8  s5      	/N  .....	/ 	/r%   c                (    dt          |            dS )NzTerminal(id=r   )idr   s     r$   r   zTerminal.__repr__=  s    )bhh))))r%   c                F    | j         st          |           | _         | j         S )z
        The subprocess enables running commands like 'ls', ['ls',
        '-l'], 'bash', 'python' and 'ipython' in the terminal.
        )r   r   rp   s    r$   rC   zTerminal.subprocess@  s(      	81$77Dr%   c                    dS NFr   rp   s    r$   closedzTerminal.closedL  s    ur%   c                    dS Nr   r   rp   s    r$   filenozTerminal.filenoP  s    rr%   c                    d S r   r   rp   s    r$   flushzTerminal.flushS  s    r%   c                    | j         S r   r   rp   s    r$   getvaluezTerminal.getvalueV  s
    {r%   c                    dS NTr   rp   s    r$   readablezTerminal.readableY      tr%   c                :    |dk    r| j         S | j         d |         S r   r   )r    sizes     r$   rw   zTerminal.read\  s$    2::;{5D5!!r%   c                    g }d}| j                             d          D ]<}|dk    r||k    r|t          j        |          z  } n|                    |           =|S )Nr   
r   )r   r   r   	getsizeofappend)r    hintlinesr   lines        r$   	readlineszTerminal.readlinesa  so    K%%d++ 	 	DbyyTD[[d+++LLr%   c                    dS r   r   rp   s    r$   seekablezTerminal.seekablek  s    ur%   c                    dS r   r   rp   s    r$   writablezTerminal.writablen  r   r%   c                :    |D ]}|                      |           d S r   )rk   )r    r   r   s      r$   
writelineszTerminal.writelinesq  s0     	 	DJJt	 	r%   r   )NNN)r   )*r   r   r   r   rN   r   r   r   optionsStringr   r   r[   rZ   r=   r   r   r   r   r   __annotations__r   rk   r   r   r   r   r   r   propertyrC   r   r   r   r   r   rw   r   r   r   r   r   r   s   @r$   r   r      s          EL3dCCCEej 9N O O OG U\" +1 2 2 2F EM4 .2 3 3 3E EM4 ./ 0 0 0E ELw <R S S SE %u}U 9: ; ; ; em FGGGGel2&&&G tt43 3G    
                "             U]9D)))/ / *)/* * * *     X    X        " " " "
             r%   r   )r   
__future__r   rf   r   r)   ri   rC   r   typingr   r   rN   pyviz_commsr   io.callbacksr   utilr	   r
   baser   Parameterizedr   r   r   r%   r$   <module>r      sG    # " " " " " 				        



 $ $ $ $ $ $ $ $  # # # # # # + + + + + + + + + + + + + +      O O O O O, O O ODV V V V Vv V V V V Vr%   