
    eZ                     &   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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mZmZmZmZ g dZ G d d	e      Zdd
Z G d de      Z G d de      Z G d de      ZddZd dlZ G d dej:                        Zy)    N   )QT_LIBmkQApp)cprint   )ClosedErrorLocalObjectProxyNoResultErrorObjectProxyRemoteEventHandler)Process	QtProcessForkedProcessr   r
   c                   *    e Zd ZdZdZddZddZd Zy)	r   a  
    Bases: RemoteEventHandler
    
    This class is used to spawn and control a new python interpreter.
    It uses subprocess.Popen to start the new process and communicates with it
    using multiprocessing.Connection objects over a network socket.
    
    By default, the remote process will immediately enter an event-processing
    loop that carries out requests send from the parent process.
    
    Remote control works mainly through proxy objects::
    
        proc = Process()              ## starts process, returns handle
        rsys = proc._import('sys')    ## asks remote process to import 'sys', returns
                                      ## a proxy which references the imported module
        rsys.stdout.write('hello
')  ## This message will be printed from the remote 
                                      ## process. Proxy objects can usually be used
                                      ## exactly as regular objects are.
        proc.close()                  ## Request the remote process shut down
    
    Requests made via proxy objects may be synchronous or asynchronous and may
    return objects either by proxy or by value (if they are picklable). See
    ProxyObject for more information.
    r   Nc	           
         |t         }|t        |       }|t        j                  }|du rdnd| _        t        j                  d      }	t        j                  j                  d|	      }
|
j                  d   }|rt        j                  }nt        j                  |      }t        j                  |j                  j!                  d	      d
      }t
        j                  j#                  t
        j                  j%                  t
        j                  j'                  |j(                        d            }t
        j                  j#                  t
        j                  j%                  t
        j                  j'                  t(              d            }| j+                  d|d|d       |r0t,        j.                  dz  dz   }t,        xj.                  dz  c_        nd}|t        j0                  j3                  d      }|rt4        j6                  }t4        j6                  }t5        j8                  ||ft4        j6                  ||      | _        t=        | j:                  j>                  d|      | _         t=        | j:                  jB                  d|      | _"        n,t5        j8                  ||ft4        j6                        | _        tG        jH                  |      }t        jJ                         }t        j0                  dk(  xr! t        jL                  t        jN                  k7  }tQ        |dz   ||	|s|nd||tR        |      }tG        jT                  || j:                  jV                         | j:                  jV                  jY                          | j+                  d|t[        |	      fz         	 	 |
j]                         }	 | j:                  jb                  }|r!|je                  |       |jg                         }ti        jj                  | ||dz   || j                         | j+                  d       tm        jn                  | j$                         y# t^        $ r}|j`                  dk(  rY d}~ d}~ww xY w)a  
        ==============  =============================================================
        **Arguments:**
        name            Optional name for this process used when printing messages
                        from the remote process.
        target          Optional function to call after starting remote process.
                        By default, this is startEventLoop(), which causes the remote
                        process to handle requests from the parent process until it
                        is asked to quit. If you wish to specify a different target,
                        it must be picklable (bound methods are not).
        copySysPath     If True, copy the contents of sys.path to the remote process.
                        If False, then only the path required to import pyqtgraph is
                        added.
        debug           If True, print detailed information about communication
                        with the child process.
        wrapStdout      If True (default on windows) then stdout and stderr from the
                        child process will be caught by the parent process and
                        forwarded to its stdout/stderr. This provides a workaround
                        for a python bug: http://bugs.python.org/issue3905
                        but has the side effect that child output is significantly
                        delayed relative to the parent output.
        pyqtapis        Formerly optional dictionary of PyQt API version numbers to set
                        before importing pyqtgraph in the remote process.
                        No longer has any effect.
        ==============  =============================================================
        NT   F   )	localhostr   authkeyr   .r   z..zbootstrap.pyzStarting child process ( )   win)stdinstdoutstderrr   r   )r   win32_child)nameportr   ppid	targetStrpathqt_libdebugz4Listening for child process on port %d, authkey=%s..   _parent)pidr'   zConnected to child process.)8startEventLoopstrsys
executabler'   osurandommultiprocessing
connectionListeneraddressr%   inspect	getmodulemodules__name__splitabspathjoindirname__file__debugMsgr   _process_countplatform
startswith
subprocessPIPEPopenprocFileForwarderr   _stdoutForwarderr   _stderrForwarderpickledumpsgetpidprefixbase_prefixdictr   dumpr   closerepracceptIOErrorerrnor*   sendrecvr   __init__atexitregister)selfr!   targetr.   copySysPathr'   timeout
wrapStdoutpyqtapisr   lr"   sysPathmodmodroot	bootstrap	procDebugr   r   r$   r*   	xchg_pidsdataconnerr	child_pids                             B/usr/lib/python3/dist-packages/pyqtgraph/multiprocess/processes.pyrW   zProcess.__init__2   sX   6 >#F<t9DJ4-QU
 **R. &&//0@'/Ryy| hhG ##F+Ckk#,,"4"4S"9!"<=Gggoobggll277??7CSCS3TVZ&[\GGGOOBGGLL1JN$[\	*iPQ  //1Q6I""a'"I007J  __F__F"((*i)@
`fouvDI %2$))2B2BHi$XD!$1$))2B2BHi$XD!"((*i)@
XDILL(	iik LLG+M

coo0M	 h%4	 	D$))//*		 	LPTVZ[bVcOddexxz IIMM	 IIcN		I##D$YIUYU_U_`34		"!  99>	s   5Q 	Q: Q54Q55Q:c                    | j                  d       | j                  j                         | j                          t	        j                         }| j                  j                         W|%t	        j                         |z
  |kD  rt        d      t	        j                  d       | j                  j                         W| j                  j                          t        | d      r|| j                  j                  j                          | j                  j                  j                          | j                  j                          | j                  j                          | j                  d| j                  j                  z         y )NzJoining child process..z,Timed out waiting for remote process to end.g?rG   zChild process exited. (%d))r>   rE   pollrP   time	Exceptionsleeprh   hasattrrG   finishsetrH   r;   
returncode)rZ   r]   starts      rk   r;   zProcess.join   s   /099>>#JJLIIKE)).."*&499;+>+H#$RSS

4  )).."* 			 4+,!!((,,.!!((,,.!!&&(!!&&(2TYY5I5IIJ    c                 &   t        | d      rV| j                  j                  5  | j                  j                  5  t	        j
                  | |g|  d d d        d d d        y t	        j
                  | |g|  y # 1 sw Y   *xY w# 1 sw Y   y xY w)NrG   )rq   rG   lockrH   r   r>   )rZ   msgargss      rk   r>   zProcess.debugMsg   s    4+,&&++ B**// B&//cADABB B ''c9D9B BB Bs"   BA;B;B	 BB)NNNTFr   NN
   )r8   
__module____qualname____doc__r?   rW   r;   r>    rv   rk   r   r      s     0 NB#JK(:rv   r   c           	         |r9dd l }t        j                  |d |j                         |t	        |      fz  d       t
        j                  j                  dt        |      f|      }|r)t        j                  |d j                         z  d       t        || ||      a
	 	 t        j                          t        j                  d       +# t        $ r- t        j                  d	       t!        j"                  d       Y 6w xY w)
Nr   =[%d] connecting to server at port localhost:%d, authkey=%s..
r   r   '[%d] connected; starting remote proxy.
r'   {Gz?zExiting server loop.)r/   r   coutrK   rQ   r1   r2   Clientintr   HANDLERprocessRequestsrn   rp   r   r>   r-   exit)r!   r"   r   r#   r'   r/   rh   s          rk   r+   r+      s    E[ ryy{D$w-89:<	>%%,,k3t9-Ew,WDEE			SUWX !tT?G
	##%JJt   	34HHQK	s   $)C 3DDc                   ,    e Zd ZdZddZd ZddZd Zy)	r   a  
    ForkedProcess is a substitute for Process that uses os.fork() to generate a new process.
    This is much faster than starting a completely new interpreter and child processes
    automatically have a copy of the entire program state from before the fork. This
    makes it an appealing approach when parallelizing expensive computations. (see
    also Parallelizer)
    
    However, fork() comes with some caveats and limitations:

      - fork() is not available on Windows.
      - It is not possible to have a QApplication in both parent and child process
        (unless both QApplications are created _after_ the call to fork())
        Attempts by the forked process to access Qt GUI elements created by the parent
        will most likely cause the child to crash.
      - Likewise, database connections are unlikely to function correctly in a forked child.
      - Threads are not copied by fork(); the new process
        will have only one thread that starts wherever fork() was called in the parent process.
      - Forked processes are unceremoniously terminated when join() is called; they are not
        given any opportunity to clean up. (This prevents them calling any cleanup code that
        was only intended to be used by the parent process)
      - Normally when fork()ing, open file handles are shared with the parent process,
        which is potentially dangerous. ForkedProcess is careful to close all file handles
        that are not explicitly needed--stdout, stderr, and a single pipe to the parent
        process.
      
    Nc           	         d| _         |dk(  r| j                  }|t        |       }t        j                         \  }}i }|2|j                         D ]  \  }}	t        j                  |	      }
|
||<   ! t        j                         }t        j                         }|dk(  rud| _        t        j                          |j                          t        j                  j                          |j!                         }t        j"                  d|       t        j"                  |dz   d       d }|t        _        dD ]v  }|t        j&                  v sdt        j&                  |d	z      _        t        j&                  j+                  |d	z   d       t        j&                  j+                  |d
z   d       x g t,        _        t-        j0                  d        |rdt        j&                  v rXt        j&                  d   j3                  t        j                         t5        t7        j6                         dz  dz        z         dt        j&                  v rXt        j&                  d   j3                  t        j                         t5        t7        j6                         dz  dz        z         t9        j:                  | ||dz   |       i | _        |j                         D ],  \  }}
t?        ||
tA        ||               | j<                  |<   . | |        yyd| _        || _!        |j                          i t8        _"        t9        j:                  | ||dz   |       t-        j0                  | jF                         y)a  
        When initializing, an optional target may be given. 
        If no target is specified, self.eventLoop will be used.
        If None is given, no target will be called (and it will be up 
        to the caller to properly shut down the forked process)
        
        preProxy may be a dict of values that will appear as ObjectProxy
        in the remote process (but do not need to be sent explicitly since 
        they are available immediately before the call to fork().
        Proxies will be availabe as self.proxies[name].
        
        If randomReseed is True, the built-in random and numpy.random generators
        will be reseeded in the child process.
        Fr   N   r   i   c                  *    dd l } |j                  |   y Nr   )	tracebackprint_exception)rz   r   s     rk   
excepthookz*ForkedProcess.__init__.<locals>.excepthook5  s     )	))40rv   )PyQt4PySidePyQt5z.QtGuiz.QtCorec                  ,    t        j                  d      S r   )r/   _exitr   rv   rk   <lambda>z(ForkedProcess.__init__.<locals>.<lambda>C  s    BHHQK rv   znumpy.randomi'  randomr    )r*   )proxyIdtypeStrTr)   )$	hasJoined	eventLoopr,   r1   Pipeitemsr	   registerObjectr/   rK   forkisParentsetpgrprP   r-   r   fileno
closeranger   r7   QApplicationpoprX   _exithandlersrY   seedr   rn   r   rW   forkedProxiesr   rQ   childPidhandlersr;   )rZ   r!   r[   preProxyrandomReseedrh   
remoteConnproxyIDskvr   r#   r*   fidr   qtlibs                   rk   rW   zForkedProcess.__init__  s    Q;^^F<t9D*//1j ( &1*99!<%& yy{ggi!8!DM JJL JJLIIOO##%CMM!S!MM#a%&1 (CN 6 ;CKK'?CCKKh/<KKOOE(ND9KKOOE)OT:	; $&F OO/0!S[[0KK/44RYY[3tyy{SXGXY^G^C_5_`s{{*KK)..ryy{SUARSXAX=Y/YZ ''j$x-TR!#D!)!1 lg+6tWVZ[cdh[iVj+k""4(l ! " !DMDM*,'''dDNLOODII&rv   c                     	 	 | j                          t        j                  d       '# t        $ r Y n5 t	        d       t        j                  t        j                           Y >xY wt        j                  d       y )Nr   z$Error occurred in forked event loop:r   )	r   rn   rp   r   printr-   r   exc_infor   rZ   s    rk   r   zForkedProcess.eventLoop_  sa    0$$&

4    0<=/s   %) 	A&0A&c                    | j                   ry 	 | j                  d|d       	 t        j                  | j
                  d       | j                  j                          d| _         y # t        $ r Y Nw xY w# t        $ r Y <w xY w)NsyncT)callSyncr]   	noCleanupr   )r   rP   rS   r/   waitpidr   OSErrorrh   )rZ   r]   s     rk   r;   zForkedProcess.joink  sx    >>	JJ4JH	JJt}}a( 			  		
  		s"   A&  A5 &	A21A25	B Bc                 n    t        j                  | j                  t        j                         d| _        y)zImmediately kill the forked remote process. 
        This is generally safe because forked processes are already
        expected to _avoid_ any cleanup at exit.TN)r/   killr   signalSIGKILLr   r   s    rk   r   zForkedProcess.kill|  s!     	v~~.rv   )Nr   NTr{   )r8   r}   r~   r   rW   r   r;   r   r   rv   rk   r   r      s    6W't
"rv   r   c                       e Zd Zd Zd Zd Zy)RemoteQtEventHandlerc                 6    t        j                  | g|i | y N)r   rW   )rZ   rz   kwdss      rk   rW   zRemoteQtEventHandler.__init__  s    ##D84848rv   c                     ddl m} |j                         | _        | j                  j                  j                  | j                         | j                  j                  d       y )Nr   QtCorer|   )Qtr   QTimertimerr]   connectr   ru   rZ   r   s     rk   startEventTimerz$RemoteQtEventHandler.startEventTimer  sB    ]]_


""4#7#78

rv   c                     	 t        j                  |        y # t        $ rK ddlm} |j
                  j                         j                          | j                  j                          Y y w xY w)Nr   	QtWidgets)
r   r   r   r   r   r   instancequitr   stop)rZ   r   s     rk   r   z$RemoteQtEventHandler.processRequests  sP    	..t4 	&""++-224JJOO	s    AA,+A,N)r8   r}   r~   rW   r   r   r   rv   rk   r   r     s    9rv   r   c                   0    e Zd ZdZd Zd ZddZd Zd Zy)	r   a  
    QtProcess is essentially the same as Process, with two major differences:
    
      - The remote process starts by running startQtEventLoop() which creates a
        QApplication in the remote process and uses a QTimer to trigger
        remote event processing. This allows the remote process to have its own
        GUI.
      - A QTimer is also started on the parent process which polls for requests
        from the child process. This allows Qt signals emitted within the child
        process to invoke slots on the parent process and vice-versa. This can
        be disabled using processRequests=False in the constructor.
      
    Example::
    
        proc = QtProcess()            
        rQtGui = proc._import('PyQt4.QtGui')
        btn = rQtWidgets.QPushButton('button on child process')
        btn.show()
        
        def slot():
            print('slot invoked on parent process')
        btn.clicked.connect(proxy(slot))   # be sure to send a proxy of the slot
    c                    d|vr	t         |d<   ddlm} |j                  dd      | _        | j                  r%|j
                  j                         t        d      t        j                  | fi | | j                          y )Nr[   r   r   r   Tz[Must create QApplication before starting QtProcess, or use QtProcess(processRequests=False))startQtEventLoopr   r   r   _processRequestsr   r   ro   r   rW   r   )rZ   r   r   s      rk   rW   zQtProcess.__init__  sv    4-DN	
 !%):D A  Y%;%;%D%D%F%Nyzz&&rv   c                 t    ddl m} |j                         | _        | j                  r| j                          y y )Nr   r   )r   r   r   r   r   startRequestProcessingr   s     rk   r   zQtProcess.startEventTimer  s,    ]]_
  '') !rv   c                     | j                   j                  j                  | j                         | j                   j	                  t        |dz               y)zStart listening for requests coming from the child process.
        This allows signals to be connected from the child process to the parent.
        i  N)r   r]   r   r   ru   r   )rZ   intervals     rk   r   z QtProcess.startRequestProcessing  s=     	

""4#7#78

Xd]+,rv   c                 8    | j                   j                          y r   )r   r   r   s    rk   stopRequestProcessingzQtProcess.stopRequestProcessing  s    

rv   c                     	 t         j                  |        y # t        $ r | j                  j	                          Y y w xY wr   )r   r   r   r   r   r   s    rk   r   zQtProcess.processRequests  s2    	##D) 	JJOO	s    #>>N)r   )	r8   r}   r~   r   rW   r   r   r   r   r   rv   rk   r   r     s     0
*-rv   r   c           	      B   |r9dd l }t        j                  |d |j                         |t	        |      fz  d       t
        j                  j                  dt        |      f|      }|r)t        j                  |d j                         z  d       ddl	m
} |j                  j                         }|t               }|j                  d	       t        || ||
      at         j#                          t%        |d      r|j'                          y |j)                          y )Nr   r   r   r   r   r   r   r   Fr   exec)r/   r   r   rK   rQ   r1   r2   r   r   r   r   r   r   r   setQuitOnLastWindowClosedr   r   r   rq   r   exec_)	r!   r"   r   r#   r'   r/   rh   r   apps	            rk   r   r     s    E[_h_a_h_h_jlprvw~r  _A  A  CE  	F%%,,k3t9-Ew,WDEE			SUWX

 
 
)
)
+C
{h%%e, #4t5AG#v&CHHJCIIKrv   c                       e Zd ZdZd Zd Zy)rF   a-  
    Background thread that forwards data from one pipe to another. 
    This is used to catch data from stdout/stderr of the child process
    and print it back out to stdout/stderr. We need this because this
    bug: http://bugs.python.org/issue3905  _requires_ us to catch
    stdout/stderr.

    *output* may be a file or 'stdout' or 'stderr'. In the latter cases,
    sys.stdout/stderr are retrieved once for every line that is output,
    which ensures that the correct behavior is achieved even if 
    sys.stdout/stderr are replaced at runtime.
    c                     t         j                  j                  |        || _        || _        t        j
                         | _        d| _        || _        t        j                         | _
        | j                          y )NT)	threadingThreadrW   inputoutputLockrx   daemoncolorEventrr   ru   )rZ   r   r   r   s       rk   rW   zFileForwarder.__init__  sW    !!$'
NN$	
oo'

rv   c                    | j                   dk(  r| j                  dur| j                  j                         s{| j                  j                         }| j                  5  t        j                  | j                  |j                  d      d       d d d        | j                  j                         szy y | j                   dk(  r| j                  dur| j                  j                         s{| j                  j                         }| j                  5  t        j                  | j                  |j                  d      d       d d d        | j                  j                         szy y t        | j                   t              rt        t        | j                         | _         | j                  j                         su| j                  j                         }| j                  5  | j                   j                  |j                  d             d d d        | j                  j                         sty y # 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   ?xY w)Nr   Futf8r   r   )r   r   rr   is_setr   readlinerx   r   r   decodecerr
isinstancer,   getattrr-   write)rZ   lines     rk   runzFileForwarder.run  s   ;;("tzz'>kk((*zz**,YY EKK

DKK,?DE kk((* [[H$5)@kk((*zz**,YY EKK

DKK,?DE kk((*
 $++s+%c4;;7kk((*zz**,YY ;KK%%dkk&&9:; kk((*E E
E E; ;s$   1H01H= +I	0H:=I	IN)r8   r}   r~   r   rW   r   r   rv   rk   rF   rF     s    ;rv   rF   )F)rX   r5   multiprocessing.connectionr1   r/   r   rB   r-   rn   rI   r   r   r   utilr   remoteproxyr   r	   r
   r   r   __all__r   r+   r   r   r   r   r   r   rF   r   rv   rk   <module>r     s      ! 	   
      T{:  {:|(X& X|- &9 9v8( (;I$$ (;rv   