B
    7Óþ[*  ã               @   s®  d Z ddlmZ dZdddddgZdd	lmZ dd
lZdd
lZddl	m	Z	m
Z
mZ dd
lZdd
lZyddlmZ W n  ek
r’   ddlmZ Y nX dd
lZdd
lZdd
lZdd
lZdd
lZe d
¡Zy ej ed¡Zej ed¡ZW n2 ek
r   ej ed¡Zej ed¡ZY nX dZdZeej dd
ƒp4dZ!e! "¡ dkrHdZ!d!dd„Z#G dd„ de$ƒZ%eeee!fdd„ƒZ&e!fdd„Z'd
a(e!fdd„Z)dd„ Z*dd„ Z+dd „ Z,d
S )"zhCapture C-level FD output on pipes

Use `wurlitzer.pipes` or `wurlitzer.sys_pipes` as context managers.
é    )Úprint_functionz1.0.2ÚpipesÚ	sys_pipesÚsys_pipes_foreverÚstop_sys_pipesÚ	Wurlitzer)ÚcontextmanagerN)ÚfcntlÚF_GETFLÚF_SETFL)ÚQueueÚstdoutÚstderrZ	__stdoutpZ	__stderrpé   é   ÚencodingÚutf8Úasciic             C   sx   d}xft td| ƒƒD ]R}yt | |¡S  tk
rf } z"|}|jtjkrTt d¡ n‚ W dd}~X Y qX qW |rt|‚dS )z Like os.dup2, but retry on EBUSYNé
   gš™™™™™¹?)	ÚrangeÚintÚosÚdup2ÚOSErrorÚerrnoZEBUSYÚtimeZsleep)ÚaÚbZtimeoutZdup_errÚiÚe© r    ú(lib/python3.7/site-packages/wurlitzer.pyr   4   s    r   c               @   sd   e Zd ZdZdZddefdd„Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ ZdS )r   ziClass for Capturing Process-level FD output via dup2
    
    Typically used via `wurlitzer.capture`
    gš™™™™™É?Nc             C   sR   || _ |tkr| j | _n|| _|| _i | _i | _i | _| j| jd< | j| jd< dS )a3  
        Parameters
        ----------
        stdout: stream or None
            The stream for forwarding stdout.
        stderr = stream or None
            The stream for forwarding stderr.
        encoding: str or None
            The encoding to use, if streams should be interpreted as text.
        r   r   N)	Ú_stdoutÚSTDOUTÚ_stderrr   Ú	_save_fdsÚ	_real_fdsZ	_handlersÚ_handle_stderrÚ_handle_stdout)Úselfr   r   r   r    r    r!   Ú__init__L   s    
zWurlitzer.__init__c             C   sp   t td| ƒ ¡ }t |¡}|| j|< t ¡ \}}t||ƒ t |¡ || j	|< t
|tƒ}t
|t|tjB ƒ |S )Nz__%s__)ÚgetattrÚsysÚfilenor   Údupr%   Úpiper   Úcloser&   r	   r
   r   Ú
O_NONBLOCK)r)   ÚnameÚreal_fdÚsave_fdZpipe_outZpipe_inÚflagsr    r    r!   Ú_setup_pipec   s    





zWurlitzer._setup_pipec             C   s   | j r| | j d¡}|S )z\Decode data, if any
        
        Called before passing to stdout/stderr streams
        Úreplace)r   Údecode)r)   Údatar    r    r!   Ú_decoder   s    zWurlitzer._decodec             C   s   | j r| j  |  |¡¡ d S )N)r"   Úwriter:   )r)   r9   r    r    r!   r(   {   s    zWurlitzer._handle_stdoutc             C   s   | j r| j  |  |¡¡ d S )N)r$   r;   r:   )r)   r9   r    r    r!   r'      s    zWurlitzer._handle_stderrc             C   s   | j | jf| _dS )zSetup handle for output, if anyN)r"   r$   Úhandle)r)   r    r    r!   Ú_setup_handleƒ   s    zWurlitzer._setup_handlec             C   s   dS )zCFinish handle, if anything should be done when it's all wrapped up.Nr    )r)   r    r    r!   Ú_finish_handle‡   s    zWurlitzer._finish_handlec                sè   t  t¡ t  t¡ ˆ ¡  t ¡ \ˆ_ˆ_ˆjg‰ˆjdi‰ˆj	r`ˆ 
d¡}ˆ |¡ dˆ|< ˆjr‚ˆ 
d¡}ˆ |¡ dˆ|< tƒ ‰ ‡ fdd„}tj|d‰dˆ_ˆ ¡  ‡ ‡‡‡‡fdd	„}tj|dˆ_dˆj_ˆj ¡  ˆjS )
NZcontrolr   r   c                 s2   x,ˆ   ¡ } | dkrd S t t¡ t t¡ qW d S )NÚstop)ÚgetÚlibcÚfflushÚ
c_stdout_pÚ
c_stderr_p)Úmsg)Úflush_queuer    r!   Ú
flush_main£   s    
z'Wurlitzer.__enter__.<locals>.flush_main)ÚtargetTc        	         sð   d} d}xÂˆrÊt   ˆg g |¡\}}}|r.d}n| r6P nˆ  d¡ ˆj}q
xx|D ]p}|ˆjkrzd} t ˆj¡ ˆ ˆj¡ qNˆ| }t |d¡}|s¨t |¡ ˆ |¡ qNtˆd| ƒ}||ƒ qNW ˆs
P q
W ˆ  d¡ ˆ 	¡  dd	„ ˆD ƒ d
S )z*Forward bytes on a pipe to stream messagesFr   ÚflushTi   z
_handle_%sr?   c             S   s   g | ]}t  |¡‘qS r    )r   r0   )Ú.0r/   r    r    r!   ú
<listcomp>Û   s    z:Wurlitzer.__enter__.<locals>.forwarder.<locals>.<listcomp>N)
ÚselectZputÚflush_intervalÚ
_control_rr   r0   ÚremoveÚreadr+   Újoin)	ZdrainingrM   ÚrÚwÚxr/   r2   r9   Zhandler)rF   Úflush_threadÚnamesr   r)   r    r!   Ú	forwarder¯   s:    




z&Wurlitzer.__enter__.<locals>.forwarder)rA   rB   rC   rD   r=   r   r/   rN   Ú
_control_wr"   r6   Úappendr$   r   Ú	threadingZThreadZdaemonÚstartÚthreadr<   )r)   r/   rG   rW   r    )rF   rU   rV   r   r)   r!   Ú	__enter__‹   s0    






.
zWurlitzer.__enter__c             C   sz   t  t¡ t  t¡ t | jd¡ | j ¡  t 	| j¡ x4| j
 ¡ D ]&\}}| j| }t||ƒ t 	|¡ qDW |  ¡  d S )Nó   )rA   rB   rC   rD   r   r;   rX   r\   rQ   r0   r&   Úitemsr%   r   r>   )r)   Úexc_typeÚ	exc_valueÚ	tracebackr2   r3   r4   r    r    r!   Ú__exit__ã   s    




zWurlitzer.__exit__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rM   Ú_default_encodingr*   r6   r:   r(   r'   r=   r>   r]   rc   r    r    r    r!   r   E   s   	Xc          	   c   s  d }}| t krPt ¡ \}}t |d¡}|r>tj|d|d}nt |d¡}d}n|  }}|tkrjd}|}nP|t kr²t ¡ \}}t |d¡}|r tj|d|d}nt |d¡}d}n| }}|sÂ|rÈd}	n|}	t|||	d}
z|
 ||fV  W dQ R X W d|r| ¡  |r| ¡  X dS )	a  Capture C-level stdout/stderr in a context manager.

    The return value for the context manager is (stdout, stderr).

    Examples
    --------

    >>> with capture() as (stdout, stderr):
    ...     printf("C-level stdout")
    ... output = stdout.read()
    FÚwbrR   )r   ÚrbTN)r   r   r   )	ÚPIPEr   r/   ÚfdopenÚioÚopenr#   r   r0   )r   r   r   Zstdout_pipeZstderr_pipeZstdout_rZstdout_wZstderr_rZstderr_wZcapture_encodingrS   r    r    r!   r   õ   s>    c             C   s   t tjtj| dS )zâRedirect C-level stdout/stderr to sys.stdout/stderr
    
    This is useful of sys.sdout/stderr are already being forwarded somewhere.
    
    DO NOT USE THIS if sys.stdout and sys.stderr are not already being forwarded.
    )r   )r   r,   r   r   )r   r    r    r!   r   ,  s    c             C   s   t dkrt| ƒa t  ¡  dS )zzRedirect all C output to sys.stdout/err
    
    This is not a context manager; it turns on C-forwarding permanently.
    N)Ú_mighty_wurlitzerr   r]   )r   r    r    r!   r   8  s    c               C   s   t dk	rt  ddd¡ da dS )z7Stop permanent redirection started by sys_pipes_foreverN)ro   rc   r    r    r    r!   r   C  s    c             C   s8   t | dƒst d¡ dS | j dt¡ | j dt¡ dS )zºRegister me as an IPython extension
    
    Captures all C output during execution and forwards to sys.
    
    Does nothing on terminal IPython.
    
    Use: %load_ext wurlitzer
    Úkernelz;wurlitzer extension doesn't do anything in terminal IPythonNÚpre_executeÚpost_execute)r+   ÚwarningsÚwarnÚeventsÚregisterr   r   )Úipr    r    r!   Úload_ipython_extensionK  s    	
rx   c             C   s.   t | dƒsdS | j dt¡ | j dt¡ dS )zJUnload me as an IPython extension
    
    Use: %unload_ext wurlitzer
    rp   Nrq   rr   )r+   ru   Z
unregisterr   r   )rw   r    r    r!   Úunload_ipython_extension]  s    
ry   )r   )-rg   Z
__future__r   Ú__version__Ú__all__Ú
contextlibr   Zctypesr   r	   r
   r   rm   r   Zqueuer   ÚImportErrorrL   r,   rZ   r   rs   ZCDLLrA   Zc_void_pZin_dllrC   rD   Ú
ValueErrorr#   rk   r+   Ústdinrh   Úlowerr   Úobjectr   r   r   ro   r   r   rx   ry   r    r    r    r!   Ú<module>   sZ   

 16
