
    	eS.                        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          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   r   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   )r/   )r*   argr   s     r#   r,   z2TerminalSubprocess._clean_args.<locals>.<listcomp>L   s%    555DKK$$555r$   )
isinstancestrr/   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)ptyr7   
ValueErrorrunningr8   r!   fork
subprocessrunprintr4   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   r7   r!   r>   	child_pidfdresultes           r#   rC   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rN   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)rG   r   nrowsncolsfcntlstructtermiospackioctl
TIOCSWINSZOSError)r   r[   r\   r]   winsizes        r#   rH   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
)	rF   _resetoskillpggetpgidsignalSIGTERMr   write)r   eventsrR   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)
rG   rF   rK   stoprP   r   rM   unwatchrQ   r@   r   s    r#   rd   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)re   readrangedecodeUnicodeDecodeErrorUnicodeError)r   rS   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 rq   )	rG   select_timeout_secr   _max_read_bytesrd   rt   r   rj   )r   
data_readyr~   outputs       r#   rI   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)rG   re   rj   r   r<   encoder   rk   s     r#   rO   z8TerminalSubprocess._forward_terminal_input_to_subprocess   sA    8 	>HTXt~3::<<=====	> 	>r$   r7   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 )r7   r3   r4   r?   splitr6   s     r#   _validate_argsz!TerminalSubprocess._validate_args   sk    ydC   	SD[[*t * *jjoo* *  	 	[[r$   rJ   c                :    | j         r| j        | j         _        d S d S r   )rK   rJ   r;   ro   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=))r7   r@   r   depths     r#   __repr__zTerminalSubprocess.__repr__   s    N$)NNt|NNNNr$   )r   r   )+__name__
__module____qualname____doc__rM   ClassSelectorr4   r5   r7   Actionr   Dictr!   Booleanr@   IntegerrF   rG   r   r   rK   rJ   	Parameterr   r   rP   r   staticmethodr/   r8   rC   dependsrH   r   rd   rt   r   rI   rO   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 4> ? ? ?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&   )r3   r4   bytesrx   r   r   len)r   _Terminal__scleaneds      r#   rj   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
   r3   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<   rM   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   rV   c                `    | j         r&t          j                            | j                   d S d S r   )r   sys
__stdout__rj   r   ro   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   ro   s    r#   rB   zTerminal.subprocess@  s(      	81$77Dr$   c                    dS NFr   ro   s    r#   closedzTerminal.closedL  s    ur$   c                    dS Nr   r   ro   s    r#   filenozTerminal.filenoP  s    rr$   c                    d S r   r   ro   s    r#   flushzTerminal.flushS  s    r$   c                    | j         S r   r   ro   s    r#   getvaluezTerminal.getvalueV  s
    {r$   c                    dS NTr   ro   s    r#   readablezTerminal.readableY      tr$   c                :    |dk    r| j         S | j         d |         S r   r   )r   sizes     r#   rv   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   ro   s    r#   seekablezTerminal.seekablek  s    ur$   c                    dS r   r   ro   s    r#   writablezTerminal.writablen  r   r$   c                :    |D ]}|                      |           d S r   )rj   )r   r   r   s      r#   
writelineszTerminal.writelinesq  s0     	 	DJJt	 	r$   r   )NNN)r   )*r   r   r   r   rM   r   r   r   optionsStringr   r   rZ   rY   r<   r   r   r   r   r   __annotations__r   rj   r   r   r   r   r   r   propertyrB   r   r   r   r   r   rv   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   re   r   r(   rh   rB   r   typingr   r   rM   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$   