
    e                        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	Z
ddlmZ  G d de      Z G d de      Z G d d	e      Z G d
 de      Z G d de      Z G d de      ZeZddZ G d de      Z G d de      Zy)    N   )cprintc                       e Zd ZdZy)ClosedErrorz}Raised when an event handler receives a request to close the connection
    or discovers that the connection has been closed.N__name__
__module____qualname____doc__     D/usr/lib/python3/dist-packages/pyqtgraph/multiprocess/remoteproxy.pyr   r      s
    9r   r   c                       e Zd ZdZy)NoResultErrorzlRaised when a request for the return value of a remote call fails
    because the call has not yet returned.Nr   r   r   r   r   r      s
    .r   r   c                       e Zd ZdZy)RemoteExceptionWarningzBEmitted when a request to a remote object results in an Exception Nr   r   r   r   r   r      s    Lr   r   c                       e Zd ZdZi ZddZed        Zd Zd Z	d Z
d Zd Zd	 Zd
 ZddZddZd Zd Zd Zd Zd Zd Zd Zd Zd Zy)RemoteEventHandlera.  
    This class handles communication between two processes. One instance is present on 
    each process and listens for communication from the other process. This enables
    (amongst other things) ObjectProxy instances to look up their attributes and call 
    their methods.
    
    This class is responsible for carrying out actions on behalf of the remote process.
    Each instance holds one end of a Connection which allows python
    objects to be passed between processes.
    
    For the most common operations, see _import(), close(), and transfer()
    
    To handle and respond to incoming requests, RemoteEventHandler requires that its
    processRequests method is called repeatedly (this is usually handled by the Process
    classes defined in multiprocess.processes).
    
    
    
    
    c                 z   || _         || _        || _        i | _        t	        j
                         | _        i | _        t	        j
                         | _        dddddt        d       t        t        t        t        t        t        t         t"        t$        g
d| _        t	        j
                         | _        d| _        d| _        t	        j
                         | _        t	        j
                         | _        |3|j3                  t5        j6                                |j9                         }| t:        j<                  |<   y )Nsync
   autoF)callSynctimeout
returnType	autoProxydeferGetattrnoProxyTypesr   )debugconnnameresults	threadingRLock
resultLockproxies	proxyLocktypestrbytesintfloattuplelistdictLocalObjectProxyObjectProxyproxyOptionsoptsLocknextRequestIdexitedprocessLocksendLocksendosgetpidrecvr   handlers)self
connectionr!   pidr   s        r   __init__zRemoteEventHandler.__init__7   s    
		 $//+"*
  !T
CUE4 +

 ") %??,!)
 ;OOBIIK(//#C+/##C(r   c                 Z    	 | j                   |   S #  t        || j                           xY wN)r<   printclsr?   s     r   
getHandlerzRemoteEventHandler.getHandlerd   s.    	<<$$	#s||$s    *c                     | j                   sy t        j                  | j                   dt        j                         t        |      |z  fz  d       y )Nz[%d] %s
)r   r   coutr9   r:   r)   )r=   msgargss      r   debugMsgzRemoteEventHandler.debugMsgl   s8    zzDJJryy{CHTM.J JBOr   c                 d    | j                   5  | j                  |   cd d d        S # 1 sw Y   y xY wrB   )r3   r2   )r=   opts     r   getProxyOptionz!RemoteEventHandler.getProxyOptionq   s,    ]] 	*$$S)	* 	* 	*s   &/c                 |    | j                   5  | j                  j                  |       ddd       y# 1 sw Y   yxY w)z~
        Set the default behavior options for object proxies.
        See ObjectProxy._setProxyOptions for more info.
        N)r3   r2   update)r=   kwdss     r   setProxyOptionsz"RemoteEventHandler.setProxyOptionsu   s4    
 ]] 	+$$T*	+ 	+ 	+s   2;c                 (   | j                   5  | j                  r| j                  d       t               d}| j                  j                         r1	 | j                          |dz  }| j                  j                         r1|dkD  r| j                  d|       |cddd       S # t        $ r | j                  d       d| _          t        d| j                  z         t        j                  t        j                           Y xY w# 1 sw Y   yxY w)	zProcess all pending requests from the pipe, return
        after no more events are immediately available. (non-blocking)
        Returns the number of events processed.
        z5  processRequests: exited already; raise ClosedError.r      zIprocessRequests: got ClosedError from handleRequest; setting exited=True.TzError in process %sz%processRequests: finished %d requestsN)r6   r5   rL   r   r    pollhandleRequestrC   r!   sys
excepthookexc_info)r=   numProcesseds     r   processRequestsz"RemoteEventHandler.processRequests}   s    
  $	 {{UV!m#L)).."4&&( A%L )).."4 aE|TI$	  $	 ( # MM"mn"&DK4/$));<NNCLLN3A$	  $	 s+   ADB$'DD$ADDDc           	      h   d}	 	 | j                   j                         \  }}}}	 | j                  d||       g }|dkD  r| j                  d	|       t        |      D ]-  }	 	 |j                  | j                   j                                / 	 |dk(  s|dk(  r|}	d}t        j                  |      }
| j                  d||
       |
j                  dd      }|dk(  r+| j                  5  d|
d   f| j                  	<   ddd       n|dk(  r0| j                  5  d|
d   |
d   ff| j                  	<   ddd       nV|dk(  rt!        |
d   |
d         }n=|dk(  r,|
d   }|
d   }|
d   }t#        |      dkD  rt%        |      D ]g  \  }}t'        |t(              st#        |      dkD  s&|d   dk(  s/|d   }|d   \  }}t+        j,                  ||   |      j/                  |      ||<   i |j1                         D ]g  \  }}t'        |t(              st#        |      dkD  s&|d   dk(  s/|d   }|d   \  }}t+        j,                  ||   |      j/                  |      ||<   i t#        |      dk(  r	  || }n ||i |}n|dk(  r|
d   }d }n|d!k(  r|
d   }d"}n|d#k(  r2t+        j,                  |d   |
d$         j/                  |
d%         }d"}n|d&k(  r|
d'   }|
j                  d(g       }t5        j6                  ||)      }t#        |      dk(  r9|j9                  d*      j;                  d*      }|}|dd D ]  }t!        ||      } n@t=        |j>                  |      }n)|d+k(  rt@        jC                  |
d,          n|d-k(  r|d}d }d}||s| j                  d.||       dk(  r7| jH                  5  | jJ                  d/   }ddd       | jM                  |      }n|d"k(  rtA        |      }	 | jO                  ||       n:| j                  d0|        | jR                  |g|  n|tE        jP                  |  |d-k(  r4
j                  d1d2      du rtU        jV                  d       yt	               y# t        $ r | j                  d       t	               t
        $ r\}|j                  dk(  r| j                  d       Y d}~| j                  d|j                  |j                         t	               d}~ww xY w# t        $ r | j                  d
       t	               t
        $ rF}|j                  dk(  r| j                  d       Y d}~| j                  d       t	               d}~ww xY w# 1 sw Y   xY w# 1 sw Y   xY w#  t3        d|t#        |      |dd fz          xY w#  tE        jF                         }Y AxY w# 1 sw Y   xY w#  tE        jP                  tE        jF                            | jR                  |gtE        jF                           Y xY w)3z^Handle a single request from the remote process. 
        Blocks until a request is available.NTz;  handleRequest: got EOFError from recv; raise ClosedError.   z4  handleRequest: got IOError 4 from recv; try again.zB  handleRequest: got IOError %d from recv (%s); raise ClosedError.z  handleRequest: received %s %sr   z+    handleRequest: reading %d byte messageszJ    handleRequest: got EOF while reading byte messages; raise ClosedError.zH    handleRequest: got IOError 4 while reading byte messages; try again.zN    handleRequest: got IOError while reading byte messages; raise ClosedError.resulterrorz     handleRequest: id=%s opts=%sr   r   	exception	excString
getObjAttrobjattrcallObjrK   rR   __byte_message__rU   r   )dtypez Failed to call object %s: %d, %sgetObjValuevaluetransferproxytransferArrayrh   shapeimportmodulefromlist)rq   .delproxyIdclosez2    handleRequest: sending return value for %d: %sr   z-    handleRequest: returning exception for %d	noCleanupF),r    r;   EOFErrorrL   r   IOErrorerrnostrerrorrangeappend
recv_bytespickleloadsgetr%   r"   getattrlen	enumerate
isinstancer-   np
frombufferreshapeitemsrC   builtins
__import__lstripsplitmap__getattr__r0   releaseProxyIdrX   rZ   r3   r2   r   replyResultrY   
replyErrorr9   _exit)r=   r_   cmdreqId	nByteMsgsoptStrerrbyteDatairesultIdoptsr   rd   fnargsfnkwdsargindrh   rn   kr!   rq   modpartspartexcr   s                              r   rW   z RemoteEventHandler.handleRequest   s?    (04		0@-UIv 	7eD q=MMGSy! 	,A,OODII$8$8$:;		,"Q	!h#.  <<'DMM<eTJ,7Jh__ H.6X-GDLL*H H__ _.5[8I4P[K\7]-^DLL*_ _$ ed6l;	!5kff x=1$!*6!2 a#%c51c#hls1vQcGc"%a&C+.q6LE5(*hsm5(Q(Y(YZ_(`F1I	a
 "( a#%c51c#hls1vQcGc"%a&C+.q6LE5(*hsm5(Q(Y(YZ_(`F1I	a v;!#!$f
 !&3F3F%e$

"e$
'x{$w-HPPQUV]Q^_$
H~88J3))$Bx=A% KK,2237E F %ab	 7!(!67 !(;F //Y@ $!F!(JC {RTY[ab' I'+'8'8'HI!^^FLAF7*-f5F<$$UF3
 MuU,,_NNC '>xxU+t3 "m# _  $[\!m# (99>MM"XYMM"fhkhqhqsvss  A%-'(&   (MM"no%-' ,yyA~&pq &vw)m+,*H H_ _4@CVV\]^]_V`CaabJ	!,,.CI I<NNCLLN3#DOOE;CLLN;s   Q= !)TAV: &U=;V: V
0A'V: V: 'V: 0A!V: V: !V: *A	V: 4V 9DV: :W6W# =,T) T 1T  T,U:4 U5U55U:=VV: 
VV:  V77V: :WW #AX1c                 B    | j                  d|dt        |             y )Nr_   off)r_   requestr   r   r   r8   r/   )r=   r   r_   s      r   r   zRemoteEventHandler.replyResultJ  s    		(%%dRXFY	Zr   c           
          t        j                  | }	 | j                  d|dt        |d   |             y #  | j                  d|dt        d |             Y y xY w)Nr`   r   rU   )ra   rb   r   )	tracebackformat_exceptionr8   r/   )r=   r   r   excStrs       r   r   zRemoteEventHandler.replyErrorM  s`    ++S1	qIIgUUX[\]X^jpIqIr	qIIgUUX\hnIoIps	   #8 "ANc                 j   | j                   r| j                  d       t               | j                  5  |i }|dv s
J d|z         |'|dk7  r(| j                  }| xj                  dz  c_        n|dv sJ |||d<   	 t        j                  |      }	d}
|t        |      }
|||
|	f}| j                  d|d   |
||       | j                  j                  |       |F|D ]&  }| j                  j                  t        |             ( | j                  dt        |             | j                  d|       |dk(  r
	 ddd       y	 ddd       t        | |t        |      |      }|dk(  r|S |dk(  r|j                         S y#  t        d	       t        |       t        d
        xY w# 1 sw Y   exY w)a]  Send a request or return packet to the remote process.
        Generally it is not necessary to call this method directly; it is for internal use.
        (The docstring has information that is nevertheless useful to the programmer
        as it describes the internal protocol used to communicate between processes)
        
        ==============  ====================================================================
        **Arguments:**
        request         String describing the type of request being sent (see below)
        reqId           Integer uniquely linking a result back to the request that generated
                        it. (most requests leave this blank)
        callSync        'sync':  return the actual result of the request
                        'async': return a Request object which can be used to look up the
                                result later
                        'off':   return no result
        timeout         Time in seconds to wait for a response when callSync=='sync'
        opts            Extra arguments sent to the remote process that determine the way
                        the request will be handled (see below)
        returnType      'proxy', 'value', or 'auto'
        byteData        If specified, this is a list of objects to be sent as byte messages
                        to the remote process.
                        This is used to send large arrays without the cost of pickling.
        ==============  ====================================================================
        
        Description of request strings and options allowed for each:
        
        =============  =============  ========================================================
        request        option         description
        -------------  -------------  --------------------------------------------------------
        getObjAttr                    Request the remote process return (proxy to) an
                                      attribute of an object.
                       obj            reference to object whose attribute should be 
                                      returned
                       attr           string name of attribute to return
                       returnValue    bool or 'auto' indicating whether to return a proxy or
                                      the actual value. 
                       
        callObj                       Request the remote process call a function or 
                                      method. If a request ID is given, then the call's
                                      return value will be sent back (or information
                                      about the error that occurred while running the
                                      function)
                       obj            the (reference to) object to call
                       args           tuple of arguments to pass to callable
                       kwds           dict of keyword arguments to pass to callable
                       returnValue    bool or 'auto' indicating whether to return a proxy or
                                      the actual value. 
                       
        getObjValue                   Request the remote process return the value of
                                      a proxied object (must be picklable)
                       obj            reference to object whose value should be returned
                       
        transfer                      Copy an object to the remote process and request
                                      it return a proxy for the new object.
                       obj            The object to transfer.
                       
        import                        Request the remote process import new symbols
                                      and return proxy(ies) to the imported objects
                       module         the string name of the module to import
                       fromlist       optional list of string names to import from module
                       
        del                           Inform the remote process that a proxy has been 
                                      released (thus the remote process may be able to 
                                      release the original object)
                       proxyId        id of proxy which is no longer referenced by 
                                      remote host
                                      
        close                         Instruct the remote process to stop its event loop
                                      and exit. Optionally, this request may return a 
                                      confirmation.
            
        result                        Inform the remote process that its request has 
                                      been processed                        
                       result         return value of a request
                       
        error                         Inform the remote process that its request failed
                       exception      the Exception that was raised (or None if the 
                                      exception could not be pickled)
                       excString      string-formatted version of the exception and 
                                      traceback
        =============  =====================================================================
        z*  send: exited already; raise ClosedError.N)r   r   asyncz:callSync must be one of "off", "sync", or "async" (got %r)r   rU   )r_   r`   r   z'====  Error pickling this object:  ====z'=======================================r   z/send request: cmd=%s nByteMsgs=%d id=%s opts=%sz  sent %d byte messagesz  call sync: %s)descriptionr   r   r   )r5   rL   r   r7   r4   r~   dumpsrC   r   r    r8   
send_bytesr*   Requestr)   r_   )r=   r   r   r   r   r   r   r   rR   r   r   rd   reqs                r   r8   zRemoteEventHandler.sendU  s   d ;;MMFG-]] /	 |77  A9u  yA  :A  A7}u$ ..E&&!+& "5555%%/\"
d+ I#M	 y&9GMMKWUVZYbdikopIINN7# ## 5CII((s457XGMM+X65 _/	 /	\ !]/	b dEs7|WMwJv::< ;?@d?@9/	 /	s%   A	F)>FB(F)$F&&F))F2c                 r    	  | j                   ddt        |      |d| d| _        y # t        $ r Y y w xY w)Nru   )rv   r   r   r   Tr   )r8   r/   r5   r   )r=   r   rv   rR   s       r   ru   zRemoteEventHandler.close  sA    	DIIagD9,EPXa\`aDK 		s   '* 	66c                    | j                   5  || j                  v }d d d        s	 | j                          | j                   5  || j                  vr
t	               | j                  j                  |      \  }}d d d        dk(  rS |dk(  r\  }|vdg}t        fd|D              s]t        j                  dt               t        j                  dj                        t               t        j                  dt               |t        dj                               t        d      t        d	      # 1 sw Y   !xY w# t        $ r Y w xY w# 1 sw Y   xY w)
Nr_   r`   AttributeErrorc              3   F   K   | ]  }d    j                  |        yw)rH   N)
startswith).0xr   s     r   	<genexpr>z/RemoteEventHandler.getResult.<locals>.<genexpr>  s      D6":003Ds   !z7===== Remote process raised exception on request: ===== z/===== Local Traceback to request follows: =====zBError getting result. See above for exception from remote process.zInternal error.)r%   r"   r\   r   r   popanywarningswarnr   joinrC   	Exception)r=   r   
haveResultstatusr_   r   normalr   s          @r   	getResultzRemoteEventHandler.getResult  sF    __ 	/$,,.J	/ $$&
 __ 	5DLL(#o%!\\--e4NFF	5
 XMw KC ++DVDDMM"[]stMM"''&/3IJMM"SUkl	bggfo& dee -..E	/ 	/  	5 	5s(   D<E	 7E<E		EEE"c                 B     | j                   dddt        |      d|S )az  
        Request the remote process import a module (or symbols from a module)
        and return the proxied results. Uses built-in __import__() function, but 
        adds a bit more processing:
        
            _import('module')  =>  returns module
            _import('module.submodule')  =>  returns submodule 
                                             (note this differs from behavior of __import__)
            _import('module', fromlist=[name1, name2, ...])  =>  returns [module.name1, module.name2, ...]
                                             (this also differs from behavior of __import__)
            
        ro   r   )rp   )r   r   r   r   r   )r=   r   rR   s      r   _importzRemoteEventHandler._import  s'     tyyZFSAQZUYZZr   c                 B     | j                   ddt        ||      d|S )Nrc   )rd   re   r   r   r   r   )r=   rd   re   rR   s       r   rc   zRemoteEventHandler.getObjAttr   s%    tyyUDSt4LUPTUUr   c                 @     | j                   ddt        |      d|S )Nri   rd   r   r   r   )r=   rd   rR   s      r   ri   zRemoteEventHandler.getObjValue#  s!    tyyKTc]KdKKr   c           	         |j                         }t        |      }| j                  5  |j                  dd       }|| j                  d   }|j                  d| j                  d         }d d d        du rL|D cg c]  }| j                  |       }}|j                         D ]  \  }}| j                  |      ||<    g }	t        |      D ][  \  }
}|j                  t        j                  k(  s$dt        |	      |j                  |j                  ff||
<   |	j                  |       ] |j                         D ][  \  }}|j                  t        j                  k(  s$dt        |	      |j                  |j                  ff||<   |	j                  |       ]  | j                  ddt!        |||      |	d|S # 1 sw Y   UxY wc c}w )	Nr   r   Trg   rf   rd   rK   rR   r   r   r   r   )copyr.   r3   r   r2   r   r   r   	__class__r   ndarrayr   rh   rn   r|   r8   r/   )r=   rd   rK   rR   r   r   r   vr   byteMsgsr   r   s               r   rf   zRemoteEventHandler.callObj&  s   yy{Dz ]] 	N88ND9L##00@d.?.?.LMI	N =ABDNN1l3BDB

 :1..L9Q:  t_ 	%EAc}}

*-s8}syy#))>TUQ$	% ::< 	#CAa{{bjj(-s8}qww>PQQ"	#
 tyyp#Dt1T_gpkopp3	N 	N Cs   AF>;G>Gc                     | j                   5  t        j                  || j                        }|j                  | j
                  |<   d d d        y # 1 sw Y   y xY wrB   )r'   weakrefrefdeleteProxy_proxyIdr&   )r=   rl   r   s      r   registerProxyz RemoteEventHandler.registerProxyF  sF    ^^ 	/++eT%5%56C %DLL	/ 	/ 	/s   :AAc                     | j                   y | j                  5  | j                  j                  |      }d d d        	 | j                  dt	              d       y # 1 sw Y   )xY w# t
        $ r Y y w xY w)Nrs   )rt   r   r   )r8   r'   r&   r   r/   r   )r=   r   rt   s      r   r   zRemoteEventHandler.deleteProxyK  sn    99^^ 	,ll&&s+G	,	IIe$w*?%IP		, 	,
  		s   AA* A'*	A65A6c                     |j                   t        j                  u r0|j                  |j                  d} | j
                  dd||gd|S  | j
                  ddt        |      d|S )z
        Transfer an object by value to the remote host (the object must be picklable) 
        and return a proxy for the new remote object.
        )rh   rn   rm   r   rk   r   r   r   )r   r   r   rh   rn   r8   r/   )r=   rd   rR   r   s       r   rk   zRemoteEventHandler.transferX  se    
 ==BJJ& YY;D499X_43%XSWXX499LZdsmLtLLr   c                 F    |D ]  }t        ||      s|c S  t        |      S rB   )r   r0   )r=   rd   r   typs       r   r   zRemoteEventHandler.autoProxyc  s-     	C#s#
	  $$r   )F)NNr   r   NN)r   F)r   r	   r
   r   r<   r@   classmethodrF   rL   rO   rS   r\   rW   r   r   r8   ru   r   r   rc   ri   rf   r   r   rk   r   r   r   r   r   r      s    ( H+0Z  P
*+) V^$D[qL \%/N[VLq@/
	M%r   r   c                   &    e Zd ZdZddZddZd Zy)r   a   
    Request objects are returned when calling an ObjectProxy in asynchronous mode
    or if a synchronous call has timed out. Use hasResult() to ask whether
    the result of the call has been returned yet. Use result() to get
    the returned value.
    Nc                 X    || _         || _        || _        d| _        d | _        || _        y )NF)procr   r   	gotResult_resultr   )r=   processr   r   r   s        r   r@   zRequest.__init__r  s-    	&
r   c                 d   | j                   r| j                  S || j                  }|rt        j                         }| j	                         s| j
                  j                  r
t               t        j                  d       |dk\  rQt        j                         |z
  |kD  r7t        d| j                  z         ddl} |j                          t               | j	                         s| j                  S | j
                  j                  | j                        | _        d| _         | j                  S )a  
        Return the result for this request. 
        
        If block is True, wait until the result has arrived or *timeout* seconds passes.
        If the timeout is reached, raise NoResultError. (use timeout=None to disable)
        If block is False, raise NoResultError immediately if the result has not arrived yet.
        
        If the process's connection has closed before the result arrives, raise ClosedError.
        Ng{Gzt?r   zRequest timed out: %sT)r   r   r   time	hasResultr   r5   r   sleeprC   r   r   print_stackr   r   r   )r=   blockr   startr   s        r   r_   zRequest.resultz  s     >><<?llGIIKEnn&99##%-'

5!a<DIIK%$7'$A1D4D4DDE$)I))+'/) nn& <<99..tzz:DL!DN<<r   c                 t    	 | j                  d       | j                  S # t        $ r Y | j                  S w xY w)z8Returns True if the result for this request has arrived.F)r   )r_   r   r   r=   s    r   r   zRequest.hasResult  s?    	KKeK$ ~~  	~~	s     	77)Nr   )TN)r   r	   r
   r   r@   r_   r   r   r   r   r   r   k  s      Dr   r   c                   T    e Zd ZdZdZi Zed        Zed        Zed        Z	d Z
d Zy)	r0   a  
    Used for wrapping local objects to ensure that they are send by proxy to a remote host.
    Note that 'proxy' is just a shorter alias for LocalObjectProxy.
    
    For example::
    
        data = [1,2,3,4,5]
        remotePlot.plot(data)         ## by default, lists are pickled and sent by value
        remotePlot.plot(proxy(data))  ## force the object to be sent by proxy
    
    r   c                 f    | j                   }| xj                   dz  c_         || j                  |<   |S )NrU   )nextProxyIdproxiedObjects)rE   rd   r?   s      r   registerObjectzLocalObjectProxy.registerObject  s0     oo1"%3
r   c                      | j                   |   S rB   r   rD   s     r   lookupProxyIdzLocalObjectProxy.lookupProxyId  s    !!#&&r   c                     | j                   |= y rB   r   rD   s     r   r   zLocalObjectProxy.releaseProxyId  s    s#r   c                 r    t        j                         | _        t        |      | _        || _        || _        y)z
        Create a 'local' proxy object that, when sent to a remote host,
        will appear as a normal ObjectProxy to *obj*. 
        Any extra keyword arguments are passed to proxy._setProxyOptions()
        on the remote side.
        N)r9   r:   	processIdreprtypeStrrd   r   )r=   rd   r   s      r   r@   zLocalObjectProxy.__init__  s*     Cy	r   c                     t         j                  | j                        }t        | j                  || j
                  d | j                  ffS rB   )r0   r   rd   unpickleObjectProxyr   r   r   )r=   r?   s     r   
__reduce__zLocalObjectProxy.__reduce__  s:     --dhh7#dnnc4<<tyy%YZZr   N)r   r	   r
   r   r   r   r   r   r   r   r@   r   r   r   r   r0   r0     sZ    
 KN   ' ' $ $[r   r0   c                     | t        j                         k(  r,t        j                  |      }||D ]  }t	        ||      } |S t        | ||      }| |j                  di | |S )N)rt   r   r   )r9   r:   r0   r   r   r1   _setProxyOptions)r   rt   r   
attributesr   rd   re   rl   s           r   r   r     sr    BIIK,,W5!" )c4()
IwH"E""*T*r   c                      e Zd ZdZd@dZd Zd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d  Z!d! Z"d" Z#d# Z$d$ Z%d% Z&d& Z'd' Z(d( Z)d) Z*d* Z+d+ Z,d, Z-d- Z.d. Z/d/ Z0d0 Z1d1 Z2d2 Z3d3 Z4d4 Z5d5 Z6d6 Z7d7 Z8d8 Z9d9 Z:d: Z;d; Z<d< Z=d= Z>d> Z?d? Z@y)Ar1   aZ  
    Proxy to an object stored by the remote process. Proxies are created
    by calling Process._import(), Process.transfer(), or by requesting/calling
    attributes on existing proxy objects.
    
    For the most part, this object can be used exactly as if it
    were a local object::
    
        rsys = proc._import('sys')   # returns proxy to sys module on remote process
        rsys.stdout                  # proxy to remote sys.stdout
        rsys.stdout.write            # proxy to remote sys.stdout.write
        rsys.stdout.write('hello')   # calls sys.stdout.write('hello') on remote machine
                                     # and returns the result (None)
    
    When calling a proxy to a remote function, the call can be made synchronous
    (result of call is returned immediately), asynchronous (result is returned later),
    or return can be disabled entirely::
    
        ros = proc._import('os')
        
        ## synchronous call; result is returned immediately
        pid = ros.getpid()
        
        ## asynchronous call
        request = ros.getpid(_callSync='async')
        while not request.hasResult():
            time.sleep(0.01)
        pid = request.result()
        
        ## disable return when we know it isn't needed
        rsys.stdout.write('hello', _callSync='off')
    
    Additionally, values returned from a remote function call are automatically
    returned either by value (must be picklable) or by proxy. 
    This behavior can be forced::
    
        rnp = proc._import('numpy')
        arrProxy = rnp.array([1,2,3,4], _returnType='proxy')
        arrValue = rnp.array([1,2,3,4], _returnType='value')
    
    The default callSync and returnType behaviors (as well as others) can be set 
    for each proxy individually using ObjectProxy._setProxyOptions() or globally using 
    proc.setProxyOptions(). 
    
    Nc                 R   t         j                  |        || j                  d<   || j                  d<   || j                  d<   d| j                  d<   d d d d d d d| j                  d<   t        j	                  |      | j                  d<   | j                  d   j                  |        y )	N
_processId_typeStrr   r   _attributes)r   r   r   r   r   r   _proxyOptions_handler)objectr@   __dict__r   rF   r   )r=   r   rt   r   parents        r   r@   zObjectProxy.__init__  s    &/l#$+j!$+j!')m$
   *
o& %7$A$A)$Lj!j!//5r   c                     |D ]  }|| j                   vst        d|z         | j                   j                  |       y)a  
        Change the behavior of this proxy. For all options, a value of None
        will cause the proxy to instead use the default behavior defined
        by its parent Process.
        
        Options are:
        
        =============  =============================================================
        callSync       'sync', 'async', 'off', or None. 
                       If 'async', then calling methods will return a Request object
                       which can be used to inquire later about the result of the 
                       method call.
                       If 'sync', then calling a method
                       will block until the remote process has returned its result
                       or the timeout has elapsed (in this case, a Request object
                       is returned instead).
                       If 'off', then the remote process is instructed _not_ to 
                       reply and the method call will return None immediately.
        returnType     'auto', 'proxy', 'value', or None. 
                       If 'proxy', then the value returned when calling a method
                       will be a proxy to the object on the remote process.
                       If 'value', then attempt to pickle the returned object and
                       send it back.
                       If 'auto', then the decision is made by consulting the
                       'noProxyTypes' option.
        autoProxy      bool or None. If True, arguments to __call__ are 
                       automatically converted to proxy unless their type is 
                       listed in noProxyTypes (see below). If False, arguments
                       are left untouched. Use proxy(obj) to manually convert
                       arguments before sending. 
        timeout        float or None. Length of time to wait during synchronous 
                       requests before returning a Request object instead.
        deferGetattr   True, False, or None. 
                       If False, all attribute requests will be sent to the remote 
                       process immediately and will block until a response is
                       received (or timeout has elapsed).
                       If True, requesting an attribute from the proxy returns a
                       new proxy immediately. The remote process is _not_ contacted
                       to make this request. This is faster, but it is possible to 
                       request an attribute that does not exist on the proxied
                       object. In this case, AttributeError will not be raised
                       until an attempt is made to look up the attribute on the
                       remote process.
        noProxyTypes   List of object types that should _not_ be proxied when
                       sent to the remote process.
        =============  =============================================================
        zUnrecognized proxy option '%s'N)r	  KeyErrorrQ   )r=   rR   r   s      r   r  zObjectProxy._setProxyOptions1  sK    `  	EA***?!CDD	E 	!!$'r   c                 8    | j                   j                  |       S )zf
        Return the value of the proxied object
        (the remote object must be picklable)
        )r
  ri   r   s    r   	_getValuezObjectProxy._getValuef  s    
 }}((..r   c                 ^    | j                   |   }|| j                  j                  |      S |S rB   )r	  r
  rO   )r=   rN   vals      r   _getProxyOptionzObjectProxy._getProxyOptionm  s1      %;==//44
r   c           	      t    t        | j                  D cg c]  }|| j                  |      f c}      S c c}w rB   )r/   r	  r  )r=   r   s     r   _getProxyOptionszObjectProxy._getProxyOptionss  s1    4;M;MNaa--a01NOONs   5c                 j    t         | j                  | j                  | j                  | j                  ffS rB   )r   r  r   r  r  r   s    r   r   zObjectProxy.__reduce__v  s)    #doot}}dmmUYUeUe%fggr   c                 N    d| j                   | j                  | j                  fz  S )Nz.<ObjectProxy for process %d, object 0x%x: %s >)r  r   r  r   s    r   __repr__zObjectProxy.__repr__y  s&    ?4??TXTaTacgcpcpBqqqr   c                     | j                         }|D ]!  }d|z   |v s|j                  d|z         ||<   # |d   du r| j                  |      S  | j                  j                  | |fi |S )aR  
        Calls __getattr__ on the remote object and returns the attribute
        by value or by proxy depending on the options set (see
        ObjectProxy._setProxyOptions and RemoteEventHandler.setProxyOptions)
        
        If the option 'deferGetattr' is True for this proxy, then a new proxy object
        is returned _without_ asking the remote object whether the named attribute exists.
        This can save time when making multiple chained attribute requests,
        but may also defer a possible AttributeError until later, making
        them more difficult to debug.
        _r   T)r  r   _deferredAttrr
  rc   )r=   re   rR   r   r   s        r   r   zObjectProxy.__getattr__~  s     $$& 	*A1u}((3q5/Q	* 4'%%d++ ,4==++D$?$??r   c                     t        | |      S rB   )DeferredObjectProxyr=   re   s     r   r  zObjectProxy._deferredAttr  s    "4..r   c                     | j                         }|D ]!  }d|z   |v s|j                  d|z         ||<   #  | j                  j                  d| ||d|S )at  
        Attempts to call the proxied object from the remote process.
        Accepts extra keyword arguments:
        
            _callSync    'off', 'sync', or 'async'
            _returnType   'value', 'proxy', or 'auto'
        
        If the remote call raises an exception on the remote process,
        it will be re-raised on the local process.
        
        r  r   r   )r  r   r
  rf   )r=   rK   rR   r   r   s        r   __call__zObjectProxy.__call__  sf     $$& 	*A1u}((3q5/Q	* %t}}$$LDtLtLLr   c                 $    | j                  |      S rB   )r  r  s     r   _getSpecialAttrzObjectProxy._getSpecialAttr  s    !!$''r   c                 *     | j                  d      | S )N__getitem__r#  r=   rK   s     r   r%  zObjectProxy.__getitem__      2t##M2D99r   c                 0     | j                  d      |ddiS )N__setitem__	_callSyncr   r&  r'  s     r   r*  zObjectProxy.__setitem__      2t##M2DJEJJr   c                 0     | j                  d      |ddiS )N__setattr__r+  r   r&  r'  s     r   r.  zObjectProxy.__setattr__  r,  r   c                 0     | j                  d      |ddiS )N__str___returnTyperj   r&  r'  s     r   r0  zObjectProxy.__str__  s    .t##I.J'JJr   c                 *     | j                  d      | S )N__len__r&  r'  s     r   r3  zObjectProxy.__len__      .t##I.55r   c                 *     | j                  d      | S )N__add__r&  r'  s     r   r6  zObjectProxy.__add__  r4  r   c                 *     | j                  d      | S )N__sub__r&  r'  s     r   r8  zObjectProxy.__sub__  r4  r   c                 *     | j                  d      | S )N__div__r&  r'  s     r   r:  zObjectProxy.__div__  r4  r   c                 *     | j                  d      | S )N__truediv__r&  r'  s     r   r<  zObjectProxy.__truediv__  r(  r   c                 *     | j                  d      | S )N__floordiv__r&  r'  s     r   r>  zObjectProxy.__floordiv__      3t##N3T::r   c                 *     | j                  d      | S )N__mul__r&  r'  s     r   rA  zObjectProxy.__mul__  r4  r   c                 *     | j                  d      | S )N__pow__r&  r'  s     r   rC  zObjectProxy.__pow__  r4  r   c                 0     | j                  d      |ddiS )N__iadd__r+  r   r&  r'  s     r   rE  zObjectProxy.__iadd__      /t##J/GGGr   c                 0     | j                  d      |ddiS )N__isub__r+  r   r&  r'  s     r   rH  zObjectProxy.__isub__  rF  r   c                 0     | j                  d      |ddiS )N__idiv__r+  r   r&  r'  s     r   rJ  zObjectProxy.__idiv__  rF  r   c                 0     | j                  d      |ddiS )N__itruediv__r+  r   r&  r'  s     r   rL  zObjectProxy.__itruediv__  s    3t##N3TKUKKr   c                 0     | j                  d      |ddiS )N__ifloordiv__r+  r   r&  r'  s     r   rN  zObjectProxy.__ifloordiv__  s    4t##O4dLeLLr   c                 0     | j                  d      |ddiS )N__imul__r+  r   r&  r'  s     r   rP  zObjectProxy.__imul__  rF  r   c                 0     | j                  d      |ddiS )N__ipow__r+  r   r&  r'  s     r   rR  zObjectProxy.__ipow__  rF  r   c                 *     | j                  d      | S )N
__rshift__r&  r'  s     r   rT  zObjectProxy.__rshift__      1t##L1488r   c                 *     | j                  d      | S )N
__lshift__r&  r'  s     r   rW  zObjectProxy.__lshift__  rU  r   c                 0     | j                  d      |ddiS )N__irshift__r+  r   r&  r'  s     r   rY  zObjectProxy.__irshift__  r,  r   c                 0     | j                  d      |ddiS )N__ilshift__r+  r   r&  r'  s     r   r[  zObjectProxy.__ilshift__  r,  r   c                 *     | j                  d      | S )N__eq__r&  r'  s     r   r]  zObjectProxy.__eq__      -t##H-t44r   c                 *     | j                  d      | S )N__ne__r&  r'  s     r   r`  zObjectProxy.__ne__  r^  r   c                 *     | j                  d      | S )N__lt__r&  r'  s     r   rb  zObjectProxy.__lt__  r^  r   c                 *     | j                  d      | S )N__gt__r&  r'  s     r   rd  zObjectProxy.__gt__  r^  r   c                 *     | j                  d      | S )N__le__r&  r'  s     r   rf  zObjectProxy.__le__  r^  r   c                 *     | j                  d      | S )N__ge__r&  r'  s     r   rh  zObjectProxy.__ge__  r^  r   c                 *     | j                  d      | S )N__and__r&  r'  s     r   rj  zObjectProxy.__and__  r4  r   c                 *     | j                  d      | S )N__or__r&  r'  s     r   rl  zObjectProxy.__or__
  r^  r   c                 *     | j                  d      | S )N__xor__r&  r'  s     r   rn  zObjectProxy.__xor__  r4  r   c                 0     | j                  d      |ddiS )N__iand__r+  r   r&  r'  s     r   rp  zObjectProxy.__iand__  rF  r   c                 0     | j                  d      |ddiS )N__ior__r+  r   r&  r'  s     r   rr  zObjectProxy.__ior__  s    .t##I.FFFr   c                 0     | j                  d      |ddiS )N__ixor__r+  r   r&  r'  s     r   rt  zObjectProxy.__ixor__  rF  r   c                 *     | j                  d      | S )N__mod__r&  r'  s     r   rv  zObjectProxy.__mod__  r4  r   c                 *     | j                  d      | S )N__radd__r&  r'  s     r   rx  zObjectProxy.__radd__      /t##J/66r   c                 *     | j                  d      | S )N__rsub__r&  r'  s     r   r{  zObjectProxy.__rsub__  ry  r   c                 *     | j                  d      | S )N__rdiv__r&  r'  s     r   r}  zObjectProxy.__rdiv__"  ry  r   c                 *     | j                  d      | S )N__rfloordiv__r&  r'  s     r   r  zObjectProxy.__rfloordiv__%  s    4t##O4d;;r   c                 *     | j                  d      | S )N__rtruediv__r&  r'  s     r   r  zObjectProxy.__rtruediv__(  r?  r   c                 *     | j                  d      | S )N__rmul__r&  r'  s     r   r  zObjectProxy.__rmul__+  ry  r   c                 *     | j                  d      | S )N__rpow__r&  r'  s     r   r  zObjectProxy.__rpow__.  ry  r   c                 *     | j                  d      | S )N__rrshift__r&  r'  s     r   r  zObjectProxy.__rrshift__1  r(  r   c                 *     | j                  d      | S )N__rlshift__r&  r'  s     r   r  zObjectProxy.__rlshift__4  r(  r   c                 *     | j                  d      | S )N__rand__r&  r'  s     r   r  zObjectProxy.__rand__7  ry  r   c                 *     | j                  d      | S N__ror__r&  r'  s     r   r  zObjectProxy.__ror__:  r4  r   c                 *     | j                  d      | S r  r&  r'  s     r   __rxor__zObjectProxy.__rxor__=  r4  r   c                 *     | j                  d      | S )N__rmod__r&  r'  s     r   r  zObjectProxy.__rmod__@  ry  r   c                     t        |       S rB   )idr   s    r   __hash__zObjectProxy.__hash__C  s    $xr   )r   N)Ar   r	   r
   r   r@   r  r  r  r  r   r  r   r  r!  r#  r%  r*  r.  r0  r3  r6  r8  r:  r<  r>  rA  rC  rE  rH  rJ  rL  rN  rP  rR  rT  rW  rY  r[  r]  r`  rb  rd  rf  rh  rj  rl  rn  rp  rr  rt  rv  rx  r{  r}  r  r  r  r  r  r  r  r  r  r  r  r   r   r   r1   r1     sN   ,Z6,3(j/Phr
@,/M*(:KKK6666:;66HHHLMHH99KK555555656HGH6777<;77::7667r   r1   c                   "    e Zd ZdZd Zd Zd Zy)r  a  
    This class represents an attribute (or sub-attribute) of a proxied object.
    It is used to speed up attribute requests. Take the following scenario::
    
        rsys = proc._import('sys')
        rsys.stdout.write('hello')
        
    For this simple example, a total of 4 synchronous requests are made to 
    the remote process: 
    
    1) import sys
    2) getattr(sys, 'stdout')
    3) getattr(stdout, 'write')
    4) write('hello')
    
    This takes a lot longer than running the equivalent code locally. To
    speed things up, we can 'defer' the two attribute lookups so they are
    only carried out when neccessary::
    
        rsys = proc._import('sys')
        rsys._setProxyOptions(deferGetattr=True)
        rsys.stdout.write('hello')
        
    This example only makes two requests to the remote process; the two 
    attribute lookups immediately return DeferredObjectProxy instances 
    immediately without contacting the remote process. When the call 
    to write() is made, all attribute requests are processed at the same time.
    
    Note that if the attributes requested do not exist on the remote object, 
    making the call to write() will raise an AttributeError.
    c                     dD ]  }t        ||      | j                  |<    || j                  d<   |j                  |fz   | j                  d<   |j                  j	                         | j                  d<   y )N)r  r  r   r
  _parentr  r	  )r   r  r  r	  r   )r=   parentProxy	attributer   s       r   r@   zDeferredObjectProxy.__init__g  sl    C 	7A&{A6DMM!	7#.i '2'>'>)'Mm$)4)B)B)G)G)Io&r   c                 j    t         j                  |       dz   dj                  | j                        z   S )Nrr   )r1   r  r   r  r   s    r   r  zDeferredObjectProxy.__repr__o  s,    ##D)C/#((4;K;K2LLLr   c                 V    | j                   j                  | j                  d   d      S )zO
        Return a non-deferred ObjectProxy referencing the same object
        rH   F)_deferGetattr)r  r   r  r   s    r   _undeferzDeferredObjectProxy._undeferr  s)     ||''(8(8(<E'RRr   N)r   r	   r
   r   r@   r  r  r   r   r   r  r  G  s    >JMSr   r  )NN)r9   rX   r#   r   r   r   r   r   r~   numpyr   utilr   r   r   r   UserWarningr   r  r   r   r0   rl   r   r1   r  r   r   r   <module>r     s    	 
         	) 	
	I 	
	[ 	I	% I	%X8f 8t6[v 6[r 	X& Xt
/S+ /Sr   