Ńņ >ģˆUc@s#dZddkZddkZddkZddkZddkZddkZddkZddkZddk Z ddk Z ddk Z ddk Z ddk Z ddkZddkiZddklZddklZddklZddklZeiiddƒdj Zde fd„ƒYZ!d e!fd „ƒYZ"d ei#fd „ƒYZ$d ei%fd„ƒYZ&dei'fd„ƒYZ(dei)fd„ƒYZ*dei+fd„ƒYZ,defd„ƒYZ-de-fd„ƒYZ.de,efd„ƒYZ/dei0fd„ƒYZ1dS(sŒ Interfaces to allow us to do RPC over pipes. The following classes are implemented to allow pipes to be used in place of file and socket objects: PipeFile PipeSocket The following classes are implemented to allow HTTP client operations over a pipe: PipedHTTPResponse PipedHTTPConnection The following classes are implemented to allow RPC servers operations over a pipe: _PipedServer _PipedTransport _PipedHTTPRequestHandler _PipedRequestHandler PipedRPCServer The following classes are implemented to allow RPC clients operations over a pipe: PipedServerProxy RPC clients should be prepared to catch the following exceptions: ProtocolError1 ProtocolError2 IOError A RPC server can be implemented as follows: server = PipedRPCServer(server_pipe_fd) server.register_introspection_functions() server.register_function(lambda x,y: x+y, 'add') server.serve_forever() A RPC client can be implemented as follows: client_rpc = PipedServerProxy(client_pipe_fd) print client_rpc.add(1, 2) del client_rpc i’’’’N(tSimpleJSONRPCRequestHandler(tSimpleJSONRPCDispatcher(t ProtocolErrortPKG_PIPEUTILS_DEBUGtPipeFilecBsƒeZdZed„Zd„Zdd„Zd„Zd„Z d„Z dd„Z d „Z d „Z d „Zd „Zd „ZRS(s³Object which makes a pipe look like a "file" object. Note that all data transmitted via this pipe is transmitted indirectly. Any data written to or read from the pipe is actually transmitted via temporary files. For sending data, the data is written to a temporary file and then the associated file descriptor is sent via the pipe. For receiving data we try to read a file descriptor from the pipe and when we get one we return the data from the temporary file associated with the file descriptor that we just read. This is done to help ensure that processes don't block while writing to these pipes (otherwise consumers of these interfaces would have to create threads to constantly drain data from these pipes to prevent clients from blocking). This class also support additional non-file special operations like sendfd() and recvfd().cCs|||_d|_t|_ti|itiƒ}|tiO}ti|iti|ƒ||_ ||_ |i dƒdS(Nt__init__( t_PipeFile__pipefdtNonet_PipeFile__readfhtFalsetclosedtfcntltF_GETFDt FD_CLOEXECtF_SETFDtdebugt debug_labelt debug_msg(tselftfdRRtflags((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR{s      cCs)|idƒ|ip|iƒndS(Nt__del__(RR tclose(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR‰s  cCs|ipdS|dj od|}nd}|idj odtiƒ|if}ndtiƒ}tid||t|ƒi|i |fIJdS(s$If debugging is enabled display msg.Ns: %sts%s: %ss%ss%s: %s.%s(%d)%s( RRRtostgetpidtsyststderrttypet__name__R(Rtoptmsgtlabel((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRŽs   cCs°|ipdSti|ƒ}ti|iƒpd|}n^ti|tidƒditi ti |ƒƒi ƒƒ}d|}ti|tidƒ|i ||ƒdS(s0If debugging is enabled dump the contents of fd.Nsfd=%diRsmsg=%s( RRtfstattstattS_ISREGtst_modetlseektSEEK_SETtjointfdopentdupt readlinesR(RRRtsiR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyt debug_dumpfd s ' cCs|iS(s$Required to support select.select().(R(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytfileno°scGs~|idj o1|ii|Œ}|djo|Sd|_n|iƒ}|djodSti|ƒ|_|i|ŒS(sPRead one entire line from the pipe. Can block waiting for input.Ri’’’’N(RRtreadlinetrecvfdRR((RtargstdataR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR.“s    i’’’’cCs~|idj o1|ii|ƒ}|djo|Sd|_n|iƒ}|djodSti|ƒ|_|i|ƒS(sSRead at most size bytes from the pipe. Can block waiting for input.Ri’’’’N(RRtreadR/RR((RtsizeR1R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR2Čs    cCsDtiƒ}|i|ƒ|iƒ|i|iƒƒ|iƒdS(sWrite a string to the pipe.N(ttempfilet TemporaryFiletwritetflushtsendfdR-R(RRtmf((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR6Üs    cCsB|iodS|idƒti|iƒd|_t|_dS(sClose the pipe.NR(R RRRRRRtTrue(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRäs    cCsdS(s.A NOP since we never do any buffering of data.N((R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR7ķscCs…|io-|iddƒtdt|ƒiƒ‚n|id|ƒyti|iti |ƒWn|iddƒ‚nXdS(s$Send a file descriptor via the pipe.R8sfailed (closed)ssendfd() called for closed %stfailedN( R RtIOErrorRRR,R tioctlRtI_SENDFD(RR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR8ńs cCs(|io-|iddƒtdt|ƒiƒ‚nyGtiddƒ}ti|i ti |ƒ}ti d|ƒd}WnCtj o7}|i t i jodS|iddƒ|‚nX|djpt‚|id|ƒti|ƒ}ti|iƒoti|tidƒn|S(s'Receive a file descriptor via the pipe.R/sfailed (closed)ssendfd() called for closed %stii’’’’iR;(R RR<RRtstructtpackR R=RtI_RECVFDtunpackterrnotENXIOtAssertionErrorR,RR!R"R#R$R%R&(Rt fcntl_argstfcntl_rvRteR+((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR/s*   N(Rt __module__t__doc__tpipeutils_debugRRRRR,R-R.R2R6RR7R8R/(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRis          t PipeSocketcBsbeZdZed„Zddd„Zdd„Zdd„Zd„Ze d „ƒZ d „Z RS( s6Object which makes a pipe look like a "socket" object.cCsti|||d|ƒdS(NR(RR(RRRR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR%stri’’’’cCsBti|iƒƒ}|idd|ƒt||id|iƒS(sÅReturn a file-like object associated with this pipe. The pipe will be duped for this new object so that the object can be closed and garbage-collected independently.tmakefiles dup fd=%dR(RR)R-RRRR(Rtmodetbufsizetdup_fd((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRO(sicCs |i|ƒS(sHReceive data from the pipe. Can block waiting for input.(R2(RRQR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytrecv2scCs |i|ƒS(sCSend data to the Socket. Should never really block.(R6(RRR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytsend8scCs|i|ƒdS(sASend data to the pipe. Should never really block.N(R6(RR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytsendall>scCsdS(s Nothing to do here. Move along.N((thow((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytshutdownCscGsdS(sset socket opt.N((RR0((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyt setsockoptIs( RRJRKRLRRORSRTRUt staticmethodRWRX(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRM"s    tPipedHTTPResponsecBseZdZd„ZRS(s¤Create a httplib.HTTPResponse like object that can be used with a pipe as a transport. We override the minimum number of parent routines necessary.cCstii|ƒt|_dS(s^Our connection will never be automatically closed, so set will_close to False.N(thttplibt HTTPResponsetbeginR t will_close(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR]Ss (RRJRKR](((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRZNstPipedHTTPConnectioncBs>eZdZeZddd„Zd„Zd„Zd„Z RS(s¦Create a httplib.HTTPConnection like object that can be used with a pipe as a transport. We override the minimum number of parent routines necessary.cCsm|djpt‚tii|dd|ƒt|ƒtjoti|ƒpt‚t |dƒ|_ dS(Nt localhosttstrictsclient-connection( RRFR[tHTTPConnectionRRtintRR!RMtsock(RRtportRa((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRds *cCs"|idj o|iƒndS(N(RdRR(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRpscCs|iiƒd|_dS(sClose our pipe fd.N(RdRR(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRus cCs |iiƒS(sRequired to support select().(RdR-(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR-zsN( RRJRKRZtresponse_classRRRRR-(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR_\s   t PipedHTTPcBs#eZdZeZed„ƒZRS(s˜Create httplib.HTTP like object that can be used with a pipe as a transport. We override the minimum number of parent routines necessary. xmlrpclib uses the legacy httplib.HTTP class interfaces (instead of the newer class httplib.HTTPConnection interfaces), so we need to provide a "Piped" compatibility class that wraps the httplib.HTTP compatibility class.cCs |iiS(sNReturn the "socket" associated with this HTTP pipe connection.(t_connRd(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRd‹s(RRJRKR_t_connection_classtpropertyRd(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRgst_PipedTransportcBsAeZdZed„Zd„Zd„Zd„Zdd„ZRS(sbCreate a Transport object which can create new PipedHTTP connections via an existing pipe.cCsAt|dƒ|_||_tii|ƒt|_d|_ dS(Nsclient-transport( Rt_PipedTransport__pipe_filet_PipedTransport__http_enctrpct TransportRR tverboseRt_extra_headers(RRthttp_enc((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR–s   cCs"|idj o|iƒndS(N(RlRR(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRscCs|iiƒd|_dS(s.Close the pipe associated with this transport.N(RlRR(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR¢s cCsœ|idj pt‚tiƒ\}}|ii|ƒti|ƒditi ƒd ƒ}|i o&|djo t |ƒSt |ƒSnt |dƒS(sUCreate a new PipedHTTP connection to the server. This involves creating a new pipe, and sending one end of the pipe to the server, and then wrapping the local end of the pipe with a PipedHTTPConnection object. This object can then be subsequently used to issue http requests.t.is2.7sclient-connectionN(RlRRFRtpipeR8RR'tplatformtpython_version_tupleRmR_RgRM(Rthostt client_pipefdt server_pipefdt py_version((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytmake_connection§s    icCsV|iotii|||||ƒS|i|ƒ}|i|ƒ|i|iƒƒS(sSend a request to the server.(RmRnRotrequestR{RTtparse_responseRO(RRwthandlert request_bodyRptc((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR|Ćs    ( RRJRKR:RRRR{R|(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRk’s     t _PipedServercBs2eZdZd„Zd„Zd„Zd„ZRS(s%Modeled after SocketServer.TCPServer.cCs;t|dƒ|_t|_tii|ddd|ƒdS(Nsserver-transporttserver_addressR`tRequestHandlerClass(Rt_PipedServer__pipe_fileR t _PipedServer__shutdown_initiatedt SocketServert BaseServerR(RRRƒ((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRŌs  cCs |iiƒS(s$Required to support select.select().(R„R-(R((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR-ÜscCsJ|iodSt|_d„}tid|d|fƒ}|iƒdS(sœTrigger a shutdown of the RPC server. This is done via a separate thread since the shutdown() entry point is non-reentrant.NcSs|iƒdS(sShutdown the server thread.N(RW(t server_obj((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyt shutdown_selfésttargetR0(R…R:t threadingtThreadtstart(RR‰tt((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytinitiate_shutdownąs    cCsI|iiƒ}|djo|iƒtiƒ‚nt|dƒdfS(sµGet a request from the client. Returns a tuple containing the request and the client address (mirroring the return value from self.socket.accept()).i’’’’sserver-connectionR`N(s localhostN(R„R/RtsocketterrorRMR(RR((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyt get_requestńs    (RRJRKRR-RR’(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRŃs    t_PipedHTTPRequestHandlercBseZdZd„ZRS(s7Piped RPC request handler that uses HTTP encapsulation.cCs ti|ƒ}|iiƒ|S(sPrepare to handle a request.(tSimpleRPCRequestHandlertsetupt connectionR(Rtrv((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR•s (RRJRKR•(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR“’st_PipedRequestHandlercBseZdZd„ZRS(s>Piped RPC request handler that doesn't use HTTP encapsulation.cCsĀ|iiƒ}d}y|ii|ƒ}WnstitiƒIJtiƒiƒ}d|d|df}t i dd|ƒ}|i ƒ}|ii ƒnX|i i|ƒ|i iƒdS(sHandle one client request.Rs%s | %siż’’’i’’’’i„€’’sServer error: %sN(trfileR.tservert_marshaled_dispatchRRt tracebackt format_exct splitlinestrpclibtFaulttresponseRtwfileR6R7(RR|R”t err_linest trace_stringtfault((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pythandle_one_requests   (RRJRKR¦(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR˜ stPipedRPCServercBsDeZdZeded„Zd„Zd„Zd„Z d„Z RS(s›Modeled after SimpleRPCServer. Differs in that SimpleRPCServer is derived from SocketServer.TCPServer but we're derived from _PipedServer.cCsG||_ti||ƒt}|p t}nti|||ƒdS(N(t logRequeststSimpleRPCDispatcherRR“R˜R(RtaddrRØtencodingRrtrequestHandler((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR2s   cCs)t|ƒtijodS|iƒdS(s]Check if a response is actually a fault object. If so then it's time to die.N(RRŸR R(RR”((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyt__check_for_server_errors>scOs&ti|||Ž}|i|ƒ|S(sPCheck for unexpected server exceptions while handling a request.(R©t _dispatcht(_PipedRPCServer__check_for_server_errors(RR0tkwargsR”((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR®Hs cOs&ti|||Ž}|i|ƒ|S(sPCheck for unexpected server exceptions while handling a request.(R©t_marshaled_single_dispatchRÆ(RR0R°R”((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR±Ss cOs&ti|||Ž}|i|ƒ|S(sPCheck for unexpected server exceptions while handling a request.(R©R›RÆ(RR0R°R”((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR›^s N( RRJRKR RR:RRÆR®R±R›(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR§-s  tPipedServerProxycBs#eZdZddded„ZRS(soCreate a ServerProxy object that can be used to make calls to an RPC server on the other end of a pipe.ic CsGt|d|ƒ|_tii|dd|id|d|d|ƒdS(NRrshttp://localhost/RPC2t transportR«Rptversion(Rkt"_PipedServerProxy__piped_transportRnt ServerProxyR(RtpipefdR«RpR“Rr((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyRns     N(RRJRKRR:R(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pyR²js (2RKR†RDR R[RRuRR"R@RR4R‹Rœt jsonrpclibRŸtjsonrpclib.jsonrpctjsonrpcRntjsonrpclib.SimpleJSONRPCServerRR”RR©RtProtocolError1t xmlrpclibtProtocolError2tenvirontgetRRLtobjectRRMR\RZRbR_tHTTPRgRoRkR‡RR“R˜R§R¶R²(((s3/usr/lib/python2.6/vendor-packages/pkg/pipeutils.pytEs>              ¹,#?. =