o
    3gE.                     @  s   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mZm	Z	 d dl
mZ d dlmZ G dd deZG dd	 d	eeZG d
d deZG dd deZG dd deZedZG dd dZG dd deZG dd dZdS )    )annotationsN)BaseCommandrun_proc)ProcessExecutionError)PopenAddonsc                   @     e Zd ZdZdS )ShellSessionErrorzqRaises when something goes wrong when calling
    :func:`ShellSession.popen <plumbum.session.ShellSession.popen>`N__name__
__module____qualname____doc__ r   r   P/home/garg/my-data/venv/lib/python3.10/site-packages/plumbum/machines/session.pyr          r   c                   @  r   )SSHCommsErrorz^Raises when the communication channel can't be created on the
    remote host or it times out.Nr	   r   r   r   r   r      r   r   c                   @  r   )SSHCommsChannel2Errorz/Raises when channel 2 (stderr) is not availableNr	   r   r   r   r   r      r   r   c                   @  r   )IncorrectLoginz4Raises when incorrect login credentials are providedNr	   r   r   r   r   r      r   r   c                   @  r   )HostPublicKeyUnknownz+Raises when the host public key isn't knownNr	   r   r   r   r   r       r   r   zplumbum.shellc                   @  s0   e Zd ZdZg dZdd Zdd Zdd Zd	S )

MarkedPipezA pipe-like object from which you can read lines; the pipe will return report EOF (the
    empty string) when a special marker is detected)pipemarker__weakref__c                 C  s   || _ || _t| jd| _d S )Nascii)r   r   bytes)selfr   r   r   r   r   __init__0   s   zMarkedPipe.__init__c                 C  s   |   r		 |   sd| _dS )zI'Closes' the marked pipe; following calls to ``readline`` will return "" N)readliner   r   r   r   r   close5   s   
zMarkedPipe.closec                 C  s>   | j du rdS | j  }|st | | jkrd| _ dS |S )zReads the next line from the pipe; returns "" when the special marker is reached.
        Raises ``EOFError`` if the underlying pipe has closedN    )r   r   EOFErrorstripr   )r   liner   r   r   r   <   s   

zMarkedPipe.readlineN)r
   r   r   r   	__slots__r   r   r   r   r   r   r   r   *   s    r   c                   @  s2   e Zd ZdZdd Zdd Zdd Zdd	d
ZdS )SessionPopenzA shell-session-based ``Popen``-like object (has the following attributes: ``stdin``,
    ``stdout``, ``stderr``, ``returncode``)c          	      C  s@   || _ || _|| _|| _|| _|| _|| _|| _d | _d| _	d S )NF)
hostprocargvisattystdinstdoutstderrcustom_encoding
returncode_done)	r   r'   r(   r)   r*   r+   r,   encodingr&   r   r   r   r   N   s   
zSessionPopen.__init__c                 C  s   | j r| jS dS )z@Returns the process' exit code or ``None`` if it's still runningN)r/   r.   r   r   r   r   pollZ   s   zSessionPopen.pollc                 C  s   |    | jS )z<Waits for the process to terminate and returns its exit code)communicater.   r   r   r   r   wait^   s   zSessionPopen.waitNc                 C  s6  g }g }d|| j fg}| js|d|| jf d}|r|r4|dd }| j| | j  |dd }|d t| }|| \}}}	z|	 }
t	
d||
 W n ty } z~t	
d| | j  | jj}d	|| jd
}d	|| jd
}| j| jd
ddd }|dkrt||||d| jdd|dkrt||||d| jdd|dkrt||||d| jdd|dkrt||||d| jddt||||d| jd|d}~ww |
s||= n||
 |s| jr|d z
t|d| _W n ttfy	   d| _Y nw d| _d	|}d	|}||fS )zConsumes the process' stdout and stderr until the it terminates.

        :param input: An optional bytes/buffer object to send to the process over stdin
        :returns: A tuple of (stdout, stderr)
        12r   Ni     z%s> %rz%s> Nothing returned.r    ignore;   z'Incorrect username or password provided)messager&      z1The authenticity of the host can't be establishedzSSH communication failedzJNo stderr result detected. Does the remote have Bash as the default shell?z9No communication channel detected. Does the remote exist?UnknownT)r+   r)   appendr,   r*   writeflushlenr   shell_loggerdebugr!   r'   r1   r.   joindecoder-   r(   splitr   r&   r   r   r   popint
IndexError
ValueErrorr/   )r   inputr+   r,   sourcesichunknamecollr   r#   errr.   r(   r   r   r   r2   c   s   

	6
E



zSessionPopen.communicateN)r
   r   r   r   r   r1   r3   r2   r   r   r   r   r%   J   s    r%   c                   @  s\   e Zd ZdZ	dddddZd	d
 Zdd Zdd Zdd Zdd Z	dd Z
dddZdS )ShellSessiona\  An abstraction layer over *shell sessions*. A shell session is the execution of an
    interactive shell (``/bin/sh`` or something compatible), over which you may run commands
    (sent over stdin). The output of is then read from stdout and stderr. Shell sessions are
    less "robust" than executing a process on its own, and they are susseptible to all sorts
    of malformatted-strings attacks, and there is little benefit from using them locally.
    However, they can greatly speed up remote connections, and are required for the implementation
    of :class:`SshMachine <plumbum.machines.remote.SshMachine>`, as they allow us to send multiple
    commands over a single SSH connection (setting up separate SSH connections incurs a high
    overhead). Try to avoid using shell sessions, unless you know what you're doing.

    Instances of this class may be used as *context-managers*.

    :param proc: The underlying shell process (with open stdin, stdout and stderr)
    :param encoding: The encoding to use for the shell session. If ``"auto"``, the underlying
                     process' encoding is used.
    :param isatty: If true, assume the shell has a TTY and that stdout and stderr are unified
    :param connect_timeout: The timeout to connect to the shell, after which, if no prompt
                            is seen, the shell process is killed
    autoFr9   Nr&   c                  s   |_ _|dkrjn|_|_t _d _d _ r2 fdd}t	 |}|
  zd_W  rB|  d S d S  rK|  w w )NrT   c                     s   t d    d S )Nz#Connection to %s timed out (%d sec))rB   errorr   r   connect_timeoutr'   r   r   r   closer   s   z%ShellSession.__init__.<locals>.closer )r&   r'   r-   r)   	threadingRLock_lock_current_startup_resultTimerstartruncancel)r   r'   r0   r)   rX   r&   rY   timerr   rW   r   r      s$   

zShellSession.__init__c                 C  s   | S rR   r   r   r   r   r   	__enter__   s   zShellSession.__enter__c                 C  s   |    d S rR   )r   )r   tvtbr   r   r   __exit__   s   zShellSession.__exit__c                 C  s8   t t |   W d    d S 1 sw   Y  d S rR   )
contextlibsuppress	Exceptionr   r   r   r   r   __del__   s   
"zShellSession.__del__c                 C  s   | j o	| j  du S )zNReturns ``True`` if the underlying shell process is alive, ``False`` otherwiseN)r'   r1   r   r   r   r   alive   s   zShellSession.alivec              	   C  s   |   sdS ttt | jjd | jj  t	
d W d   n1 s)w   Y  | jj| jj| jjfD ]}tt |  W d   n1 sOw   Y  q9tt | j  W d   n1 sjw   Y  d| _dS )z%Closes (terminates) the shell sessionNs   
exit


exit

g?)rn   rj   rk   rJ   OSErrorr'   r*   r?   r@   timesleepr+   r,   rl   r   kill)r   pr   r   r   r      s    

zShellSession.closec              
   C  s  | j du r	td| jr| jjstdt|tr|dn|}dt t   d}|	 r5|d7 }nd}|d	| d
7 }| j
sJ|d| d7 }| jrS|| j}td| | j j|d  | j j  t| j || j
| j jt| j j|t| j j|| j| jd| _| jS )aa  Runs the given command in the shell, adding some decoration around it. Only a single
        command can be executed at any given time.

        :param cmd: The command (string or :class:`Command <plumbum.commands.BaseCommand>` object)
                    to run
        :returns: A :class:`SessionPopen <plumbum.session.SessionPopen>` instance
        Nz%Shell session has already been closedz/Each shell may start only one process at a timer6   z--.ENDz.--z ; ztrue ; zecho $? ; echo ''z	 ; echo 'z' 1>&2z
Running %r   
rU   )r'   r   r^   r/   
isinstancer   	formulaterp   randomr"   r)   r-   encoderB   rC   r*   r?   r@   r%   r   r+   r,   r&   )r   cmdfull_cmdr   r   r   r   popen  s8   


zShellSession.popenr   c                 C  s:   | j  t| ||W  d   S 1 sw   Y  dS )al  Runs the given command

        :param cmd: The command (string or :class:`Command <plumbum.commands.BaseCommand>` object)
                    to run
        :param retcode: The expected return code (0 by default). Set to ``None`` in order to
                        ignore erroneous return codes
        :returns: A tuple of (return code, stdout, stderr)
        N)r]   r   r|   )r   rz   retcoder   r   r   rb   4  s   	$zShellSession.run)rT   Fr9   )r   )r
   r   r   r   r   re   ri   rm   rn   r   r|   rb   r   r   r   r   rS      s    'rS   )
__future__r   rj   loggingrx   r[   rp   plumbum.commandsr   r   plumbum.commands.processesr   plumbum.machines.baser   rl   r   r!   r   r   r   r   	getLoggerrB   r   r%   rS   r   r   r   r   <module>   s$    
 w