Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib64/python2..../idlelib
File: rpc.py
"""RPC Implementation, originally written for the Python Idle IDE
[0] Fix | Delete
[1] Fix | Delete
For security reasons, GvR requested that Idle's Python execution server process
[2] Fix | Delete
connect to the Idle process, which listens for the connection. Since Idle has
[3] Fix | Delete
only one client per server, this was not a limitation.
[4] Fix | Delete
[5] Fix | Delete
+---------------------------------+ +-------------+
[6] Fix | Delete
| SocketServer.BaseRequestHandler | | SocketIO |
[7] Fix | Delete
+---------------------------------+ +-------------+
[8] Fix | Delete
^ | register() |
[9] Fix | Delete
| | unregister()|
[10] Fix | Delete
| +-------------+
[11] Fix | Delete
| ^ ^
[12] Fix | Delete
| | |
[13] Fix | Delete
| + -------------------+ |
[14] Fix | Delete
| | |
[15] Fix | Delete
+-------------------------+ +-----------------+
[16] Fix | Delete
| RPCHandler | | RPCClient |
[17] Fix | Delete
| [attribute of RPCServer]| | |
[18] Fix | Delete
+-------------------------+ +-----------------+
[19] Fix | Delete
[20] Fix | Delete
The RPCServer handler class is expected to provide register/unregister methods.
[21] Fix | Delete
RPCHandler inherits the mix-in class SocketIO, which provides these methods.
[22] Fix | Delete
[23] Fix | Delete
See the Idle run.main() docstring for further information on how this was
[24] Fix | Delete
accomplished in Idle.
[25] Fix | Delete
[26] Fix | Delete
"""
[27] Fix | Delete
[28] Fix | Delete
import sys
[29] Fix | Delete
import os
[30] Fix | Delete
import socket
[31] Fix | Delete
import select
[32] Fix | Delete
import SocketServer
[33] Fix | Delete
import struct
[34] Fix | Delete
import cPickle as pickle
[35] Fix | Delete
import threading
[36] Fix | Delete
import Queue
[37] Fix | Delete
import traceback
[38] Fix | Delete
import copy_reg
[39] Fix | Delete
import types
[40] Fix | Delete
import marshal
[41] Fix | Delete
[42] Fix | Delete
[43] Fix | Delete
def unpickle_code(ms):
[44] Fix | Delete
co = marshal.loads(ms)
[45] Fix | Delete
assert isinstance(co, types.CodeType)
[46] Fix | Delete
return co
[47] Fix | Delete
[48] Fix | Delete
def pickle_code(co):
[49] Fix | Delete
assert isinstance(co, types.CodeType)
[50] Fix | Delete
ms = marshal.dumps(co)
[51] Fix | Delete
return unpickle_code, (ms,)
[52] Fix | Delete
[53] Fix | Delete
# XXX KBK 24Aug02 function pickling capability not used in Idle
[54] Fix | Delete
# def unpickle_function(ms):
[55] Fix | Delete
# return ms
[56] Fix | Delete
[57] Fix | Delete
# def pickle_function(fn):
[58] Fix | Delete
# assert isinstance(fn, type.FunctionType)
[59] Fix | Delete
# return repr(fn)
[60] Fix | Delete
[61] Fix | Delete
copy_reg.pickle(types.CodeType, pickle_code, unpickle_code)
[62] Fix | Delete
# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function)
[63] Fix | Delete
[64] Fix | Delete
BUFSIZE = 8*1024
[65] Fix | Delete
LOCALHOST = '127.0.0.1'
[66] Fix | Delete
[67] Fix | Delete
class RPCServer(SocketServer.TCPServer):
[68] Fix | Delete
[69] Fix | Delete
def __init__(self, addr, handlerclass=None):
[70] Fix | Delete
if handlerclass is None:
[71] Fix | Delete
handlerclass = RPCHandler
[72] Fix | Delete
SocketServer.TCPServer.__init__(self, addr, handlerclass)
[73] Fix | Delete
[74] Fix | Delete
def server_bind(self):
[75] Fix | Delete
"Override TCPServer method, no bind() phase for connecting entity"
[76] Fix | Delete
pass
[77] Fix | Delete
[78] Fix | Delete
def server_activate(self):
[79] Fix | Delete
"""Override TCPServer method, connect() instead of listen()
[80] Fix | Delete
[81] Fix | Delete
Due to the reversed connection, self.server_address is actually the
[82] Fix | Delete
address of the Idle Client to which we are connecting.
[83] Fix | Delete
[84] Fix | Delete
"""
[85] Fix | Delete
self.socket.connect(self.server_address)
[86] Fix | Delete
[87] Fix | Delete
def get_request(self):
[88] Fix | Delete
"Override TCPServer method, return already connected socket"
[89] Fix | Delete
return self.socket, self.server_address
[90] Fix | Delete
[91] Fix | Delete
def handle_error(self, request, client_address):
[92] Fix | Delete
"""Override TCPServer method
[93] Fix | Delete
[94] Fix | Delete
Error message goes to __stderr__. No error message if exiting
[95] Fix | Delete
normally or socket raised EOF. Other exceptions not handled in
[96] Fix | Delete
server code will cause os._exit.
[97] Fix | Delete
[98] Fix | Delete
"""
[99] Fix | Delete
try:
[100] Fix | Delete
raise
[101] Fix | Delete
except SystemExit:
[102] Fix | Delete
raise
[103] Fix | Delete
except:
[104] Fix | Delete
erf = sys.__stderr__
[105] Fix | Delete
print>>erf, '\n' + '-'*40
[106] Fix | Delete
print>>erf, 'Unhandled server exception!'
[107] Fix | Delete
print>>erf, 'Thread: %s' % threading.currentThread().getName()
[108] Fix | Delete
print>>erf, 'Client Address: ', client_address
[109] Fix | Delete
print>>erf, 'Request: ', repr(request)
[110] Fix | Delete
traceback.print_exc(file=erf)
[111] Fix | Delete
print>>erf, '\n*** Unrecoverable, server exiting!'
[112] Fix | Delete
print>>erf, '-'*40
[113] Fix | Delete
os._exit(0)
[114] Fix | Delete
[115] Fix | Delete
#----------------- end class RPCServer --------------------
[116] Fix | Delete
[117] Fix | Delete
objecttable = {}
[118] Fix | Delete
request_queue = Queue.Queue(0)
[119] Fix | Delete
response_queue = Queue.Queue(0)
[120] Fix | Delete
[121] Fix | Delete
[122] Fix | Delete
class SocketIO(object):
[123] Fix | Delete
[124] Fix | Delete
nextseq = 0
[125] Fix | Delete
[126] Fix | Delete
def __init__(self, sock, objtable=None, debugging=None):
[127] Fix | Delete
self.sockthread = threading.currentThread()
[128] Fix | Delete
if debugging is not None:
[129] Fix | Delete
self.debugging = debugging
[130] Fix | Delete
self.sock = sock
[131] Fix | Delete
if objtable is None:
[132] Fix | Delete
objtable = objecttable
[133] Fix | Delete
self.objtable = objtable
[134] Fix | Delete
self.responses = {}
[135] Fix | Delete
self.cvars = {}
[136] Fix | Delete
[137] Fix | Delete
def close(self):
[138] Fix | Delete
sock = self.sock
[139] Fix | Delete
self.sock = None
[140] Fix | Delete
if sock is not None:
[141] Fix | Delete
sock.close()
[142] Fix | Delete
[143] Fix | Delete
def exithook(self):
[144] Fix | Delete
"override for specific exit action"
[145] Fix | Delete
os._exit(0)
[146] Fix | Delete
[147] Fix | Delete
def debug(self, *args):
[148] Fix | Delete
if not self.debugging:
[149] Fix | Delete
return
[150] Fix | Delete
s = self.location + " " + str(threading.currentThread().getName())
[151] Fix | Delete
for a in args:
[152] Fix | Delete
s = s + " " + str(a)
[153] Fix | Delete
print>>sys.__stderr__, s
[154] Fix | Delete
[155] Fix | Delete
def register(self, oid, object):
[156] Fix | Delete
self.objtable[oid] = object
[157] Fix | Delete
[158] Fix | Delete
def unregister(self, oid):
[159] Fix | Delete
try:
[160] Fix | Delete
del self.objtable[oid]
[161] Fix | Delete
except KeyError:
[162] Fix | Delete
pass
[163] Fix | Delete
[164] Fix | Delete
def localcall(self, seq, request):
[165] Fix | Delete
self.debug("localcall:", request)
[166] Fix | Delete
try:
[167] Fix | Delete
how, (oid, methodname, args, kwargs) = request
[168] Fix | Delete
except TypeError:
[169] Fix | Delete
return ("ERROR", "Bad request format")
[170] Fix | Delete
if oid not in self.objtable:
[171] Fix | Delete
return ("ERROR", "Unknown object id: %r" % (oid,))
[172] Fix | Delete
obj = self.objtable[oid]
[173] Fix | Delete
if methodname == "__methods__":
[174] Fix | Delete
methods = {}
[175] Fix | Delete
_getmethods(obj, methods)
[176] Fix | Delete
return ("OK", methods)
[177] Fix | Delete
if methodname == "__attributes__":
[178] Fix | Delete
attributes = {}
[179] Fix | Delete
_getattributes(obj, attributes)
[180] Fix | Delete
return ("OK", attributes)
[181] Fix | Delete
if not hasattr(obj, methodname):
[182] Fix | Delete
return ("ERROR", "Unsupported method name: %r" % (methodname,))
[183] Fix | Delete
method = getattr(obj, methodname)
[184] Fix | Delete
try:
[185] Fix | Delete
if how == 'CALL':
[186] Fix | Delete
ret = method(*args, **kwargs)
[187] Fix | Delete
if isinstance(ret, RemoteObject):
[188] Fix | Delete
ret = remoteref(ret)
[189] Fix | Delete
return ("OK", ret)
[190] Fix | Delete
elif how == 'QUEUE':
[191] Fix | Delete
request_queue.put((seq, (method, args, kwargs)))
[192] Fix | Delete
return("QUEUED", None)
[193] Fix | Delete
else:
[194] Fix | Delete
return ("ERROR", "Unsupported message type: %s" % how)
[195] Fix | Delete
except SystemExit:
[196] Fix | Delete
raise
[197] Fix | Delete
except socket.error:
[198] Fix | Delete
raise
[199] Fix | Delete
except:
[200] Fix | Delete
msg = "*** Internal Error: rpc.py:SocketIO.localcall()\n\n"\
[201] Fix | Delete
" Object: %s \n Method: %s \n Args: %s\n"
[202] Fix | Delete
print>>sys.__stderr__, msg % (oid, method, args)
[203] Fix | Delete
traceback.print_exc(file=sys.__stderr__)
[204] Fix | Delete
return ("EXCEPTION", None)
[205] Fix | Delete
[206] Fix | Delete
def remotecall(self, oid, methodname, args, kwargs):
[207] Fix | Delete
self.debug("remotecall:asynccall: ", oid, methodname)
[208] Fix | Delete
seq = self.asynccall(oid, methodname, args, kwargs)
[209] Fix | Delete
return self.asyncreturn(seq)
[210] Fix | Delete
[211] Fix | Delete
def remotequeue(self, oid, methodname, args, kwargs):
[212] Fix | Delete
self.debug("remotequeue:asyncqueue: ", oid, methodname)
[213] Fix | Delete
seq = self.asyncqueue(oid, methodname, args, kwargs)
[214] Fix | Delete
return self.asyncreturn(seq)
[215] Fix | Delete
[216] Fix | Delete
def asynccall(self, oid, methodname, args, kwargs):
[217] Fix | Delete
request = ("CALL", (oid, methodname, args, kwargs))
[218] Fix | Delete
seq = self.newseq()
[219] Fix | Delete
if threading.currentThread() != self.sockthread:
[220] Fix | Delete
cvar = threading.Condition()
[221] Fix | Delete
self.cvars[seq] = cvar
[222] Fix | Delete
self.debug(("asynccall:%d:" % seq), oid, methodname, args, kwargs)
[223] Fix | Delete
self.putmessage((seq, request))
[224] Fix | Delete
return seq
[225] Fix | Delete
[226] Fix | Delete
def asyncqueue(self, oid, methodname, args, kwargs):
[227] Fix | Delete
request = ("QUEUE", (oid, methodname, args, kwargs))
[228] Fix | Delete
seq = self.newseq()
[229] Fix | Delete
if threading.currentThread() != self.sockthread:
[230] Fix | Delete
cvar = threading.Condition()
[231] Fix | Delete
self.cvars[seq] = cvar
[232] Fix | Delete
self.debug(("asyncqueue:%d:" % seq), oid, methodname, args, kwargs)
[233] Fix | Delete
self.putmessage((seq, request))
[234] Fix | Delete
return seq
[235] Fix | Delete
[236] Fix | Delete
def asyncreturn(self, seq):
[237] Fix | Delete
self.debug("asyncreturn:%d:call getresponse(): " % seq)
[238] Fix | Delete
response = self.getresponse(seq, wait=0.05)
[239] Fix | Delete
self.debug(("asyncreturn:%d:response: " % seq), response)
[240] Fix | Delete
return self.decoderesponse(response)
[241] Fix | Delete
[242] Fix | Delete
def decoderesponse(self, response):
[243] Fix | Delete
how, what = response
[244] Fix | Delete
if how == "OK":
[245] Fix | Delete
return what
[246] Fix | Delete
if how == "QUEUED":
[247] Fix | Delete
return None
[248] Fix | Delete
if how == "EXCEPTION":
[249] Fix | Delete
self.debug("decoderesponse: EXCEPTION")
[250] Fix | Delete
return None
[251] Fix | Delete
if how == "EOF":
[252] Fix | Delete
self.debug("decoderesponse: EOF")
[253] Fix | Delete
self.decode_interrupthook()
[254] Fix | Delete
return None
[255] Fix | Delete
if how == "ERROR":
[256] Fix | Delete
self.debug("decoderesponse: Internal ERROR:", what)
[257] Fix | Delete
raise RuntimeError, what
[258] Fix | Delete
raise SystemError, (how, what)
[259] Fix | Delete
[260] Fix | Delete
def decode_interrupthook(self):
[261] Fix | Delete
""
[262] Fix | Delete
raise EOFError
[263] Fix | Delete
[264] Fix | Delete
def mainloop(self):
[265] Fix | Delete
"""Listen on socket until I/O not ready or EOF
[266] Fix | Delete
[267] Fix | Delete
pollresponse() will loop looking for seq number None, which
[268] Fix | Delete
never comes, and exit on EOFError.
[269] Fix | Delete
[270] Fix | Delete
"""
[271] Fix | Delete
try:
[272] Fix | Delete
self.getresponse(myseq=None, wait=0.05)
[273] Fix | Delete
except EOFError:
[274] Fix | Delete
self.debug("mainloop:return")
[275] Fix | Delete
return
[276] Fix | Delete
[277] Fix | Delete
def getresponse(self, myseq, wait):
[278] Fix | Delete
response = self._getresponse(myseq, wait)
[279] Fix | Delete
if response is not None:
[280] Fix | Delete
how, what = response
[281] Fix | Delete
if how == "OK":
[282] Fix | Delete
response = how, self._proxify(what)
[283] Fix | Delete
return response
[284] Fix | Delete
[285] Fix | Delete
def _proxify(self, obj):
[286] Fix | Delete
if isinstance(obj, RemoteProxy):
[287] Fix | Delete
return RPCProxy(self, obj.oid)
[288] Fix | Delete
if isinstance(obj, types.ListType):
[289] Fix | Delete
return map(self._proxify, obj)
[290] Fix | Delete
# XXX Check for other types -- not currently needed
[291] Fix | Delete
return obj
[292] Fix | Delete
[293] Fix | Delete
def _getresponse(self, myseq, wait):
[294] Fix | Delete
self.debug("_getresponse:myseq:", myseq)
[295] Fix | Delete
if threading.currentThread() is self.sockthread:
[296] Fix | Delete
# this thread does all reading of requests or responses
[297] Fix | Delete
while 1:
[298] Fix | Delete
response = self.pollresponse(myseq, wait)
[299] Fix | Delete
if response is not None:
[300] Fix | Delete
return response
[301] Fix | Delete
else:
[302] Fix | Delete
# wait for notification from socket handling thread
[303] Fix | Delete
cvar = self.cvars[myseq]
[304] Fix | Delete
cvar.acquire()
[305] Fix | Delete
while myseq not in self.responses:
[306] Fix | Delete
cvar.wait()
[307] Fix | Delete
response = self.responses[myseq]
[308] Fix | Delete
self.debug("_getresponse:%s: thread woke up: response: %s" %
[309] Fix | Delete
(myseq, response))
[310] Fix | Delete
del self.responses[myseq]
[311] Fix | Delete
del self.cvars[myseq]
[312] Fix | Delete
cvar.release()
[313] Fix | Delete
return response
[314] Fix | Delete
[315] Fix | Delete
def newseq(self):
[316] Fix | Delete
self.nextseq = seq = self.nextseq + 2
[317] Fix | Delete
return seq
[318] Fix | Delete
[319] Fix | Delete
def putmessage(self, message):
[320] Fix | Delete
self.debug("putmessage:%d:" % message[0])
[321] Fix | Delete
try:
[322] Fix | Delete
s = pickle.dumps(message)
[323] Fix | Delete
except pickle.PicklingError:
[324] Fix | Delete
print >>sys.__stderr__, "Cannot pickle:", repr(message)
[325] Fix | Delete
raise
[326] Fix | Delete
s = struct.pack("<i", len(s)) + s
[327] Fix | Delete
while len(s) > 0:
[328] Fix | Delete
try:
[329] Fix | Delete
r, w, x = select.select([], [self.sock], [])
[330] Fix | Delete
n = self.sock.send(s[:BUFSIZE])
[331] Fix | Delete
except (AttributeError, TypeError):
[332] Fix | Delete
raise IOError, "socket no longer exists"
[333] Fix | Delete
s = s[n:]
[334] Fix | Delete
[335] Fix | Delete
buffer = ""
[336] Fix | Delete
bufneed = 4
[337] Fix | Delete
bufstate = 0 # meaning: 0 => reading count; 1 => reading data
[338] Fix | Delete
[339] Fix | Delete
def pollpacket(self, wait):
[340] Fix | Delete
self._stage0()
[341] Fix | Delete
if len(self.buffer) < self.bufneed:
[342] Fix | Delete
r, w, x = select.select([self.sock.fileno()], [], [], wait)
[343] Fix | Delete
if len(r) == 0:
[344] Fix | Delete
return None
[345] Fix | Delete
try:
[346] Fix | Delete
s = self.sock.recv(BUFSIZE)
[347] Fix | Delete
except socket.error:
[348] Fix | Delete
raise EOFError
[349] Fix | Delete
if len(s) == 0:
[350] Fix | Delete
raise EOFError
[351] Fix | Delete
self.buffer += s
[352] Fix | Delete
self._stage0()
[353] Fix | Delete
return self._stage1()
[354] Fix | Delete
[355] Fix | Delete
def _stage0(self):
[356] Fix | Delete
if self.bufstate == 0 and len(self.buffer) >= 4:
[357] Fix | Delete
s = self.buffer[:4]
[358] Fix | Delete
self.buffer = self.buffer[4:]
[359] Fix | Delete
self.bufneed = struct.unpack("<i", s)[0]
[360] Fix | Delete
self.bufstate = 1
[361] Fix | Delete
[362] Fix | Delete
def _stage1(self):
[363] Fix | Delete
if self.bufstate == 1 and len(self.buffer) >= self.bufneed:
[364] Fix | Delete
packet = self.buffer[:self.bufneed]
[365] Fix | Delete
self.buffer = self.buffer[self.bufneed:]
[366] Fix | Delete
self.bufneed = 4
[367] Fix | Delete
self.bufstate = 0
[368] Fix | Delete
return packet
[369] Fix | Delete
[370] Fix | Delete
def pollmessage(self, wait):
[371] Fix | Delete
packet = self.pollpacket(wait)
[372] Fix | Delete
if packet is None:
[373] Fix | Delete
return None
[374] Fix | Delete
try:
[375] Fix | Delete
message = pickle.loads(packet)
[376] Fix | Delete
except pickle.UnpicklingError:
[377] Fix | Delete
print >>sys.__stderr__, "-----------------------"
[378] Fix | Delete
print >>sys.__stderr__, "cannot unpickle packet:", repr(packet)
[379] Fix | Delete
traceback.print_stack(file=sys.__stderr__)
[380] Fix | Delete
print >>sys.__stderr__, "-----------------------"
[381] Fix | Delete
raise
[382] Fix | Delete
return message
[383] Fix | Delete
[384] Fix | Delete
def pollresponse(self, myseq, wait):
[385] Fix | Delete
"""Handle messages received on the socket.
[386] Fix | Delete
[387] Fix | Delete
Some messages received may be asynchronous 'call' or 'queue' requests,
[388] Fix | Delete
and some may be responses for other threads.
[389] Fix | Delete
[390] Fix | Delete
'call' requests are passed to self.localcall() with the expectation of
[391] Fix | Delete
immediate execution, during which time the socket is not serviced.
[392] Fix | Delete
[393] Fix | Delete
'queue' requests are used for tasks (which may block or hang) to be
[394] Fix | Delete
processed in a different thread. These requests are fed into
[395] Fix | Delete
request_queue by self.localcall(). Responses to queued requests are
[396] Fix | Delete
taken from response_queue and sent across the link with the associated
[397] Fix | Delete
sequence numbers. Messages in the queues are (sequence_number,
[398] Fix | Delete
request/response) tuples and code using this module removing messages
[399] Fix | Delete
from the request_queue is responsible for returning the correct
[400] Fix | Delete
sequence number in the response_queue.
[401] Fix | Delete
[402] Fix | Delete
pollresponse() will loop until a response message with the myseq
[403] Fix | Delete
sequence number is received, and will save other responses in
[404] Fix | Delete
self.responses and notify the owning thread.
[405] Fix | Delete
[406] Fix | Delete
"""
[407] Fix | Delete
while 1:
[408] Fix | Delete
# send queued response if there is one available
[409] Fix | Delete
try:
[410] Fix | Delete
qmsg = response_queue.get(0)
[411] Fix | Delete
except Queue.Empty:
[412] Fix | Delete
pass
[413] Fix | Delete
else:
[414] Fix | Delete
seq, response = qmsg
[415] Fix | Delete
message = (seq, ('OK', response))
[416] Fix | Delete
self.putmessage(message)
[417] Fix | Delete
# poll for message on link
[418] Fix | Delete
try:
[419] Fix | Delete
message = self.pollmessage(wait)
[420] Fix | Delete
if message is None: # socket not ready
[421] Fix | Delete
return None
[422] Fix | Delete
except EOFError:
[423] Fix | Delete
self.handle_EOF()
[424] Fix | Delete
return None
[425] Fix | Delete
except AttributeError:
[426] Fix | Delete
return None
[427] Fix | Delete
seq, resq = message
[428] Fix | Delete
how = resq[0]
[429] Fix | Delete
self.debug("pollresponse:%d:myseq:%s" % (seq, myseq))
[430] Fix | Delete
# process or queue a request
[431] Fix | Delete
if how in ("CALL", "QUEUE"):
[432] Fix | Delete
self.debug("pollresponse:%d:localcall:call:" % seq)
[433] Fix | Delete
response = self.localcall(seq, resq)
[434] Fix | Delete
self.debug("pollresponse:%d:localcall:response:%s"
[435] Fix | Delete
% (seq, response))
[436] Fix | Delete
if how == "CALL":
[437] Fix | Delete
self.putmessage((seq, response))
[438] Fix | Delete
elif how == "QUEUE":
[439] Fix | Delete
# don't acknowledge the 'queue' request!
[440] Fix | Delete
pass
[441] Fix | Delete
continue
[442] Fix | Delete
# return if completed message transaction
[443] Fix | Delete
elif seq == myseq:
[444] Fix | Delete
return resq
[445] Fix | Delete
# must be a response for a different thread:
[446] Fix | Delete
else:
[447] Fix | Delete
cv = self.cvars.get(seq, None)
[448] Fix | Delete
# response involving unknown sequence number is discarded,
[449] Fix | Delete
# probably intended for prior incarnation of server
[450] Fix | Delete
if cv is not None:
[451] Fix | Delete
cv.acquire()
[452] Fix | Delete
self.responses[seq] = resq
[453] Fix | Delete
cv.notify()
[454] Fix | Delete
cv.release()
[455] Fix | Delete
continue
[456] Fix | Delete
[457] Fix | Delete
def handle_EOF(self):
[458] Fix | Delete
"action taken upon link being closed by peer"
[459] Fix | Delete
self.EOFhook()
[460] Fix | Delete
self.debug("handle_EOF")
[461] Fix | Delete
for key in self.cvars:
[462] Fix | Delete
cv = self.cvars[key]
[463] Fix | Delete
cv.acquire()
[464] Fix | Delete
self.responses[key] = ('EOF', None)
[465] Fix | Delete
cv.notify()
[466] Fix | Delete
cv.release()
[467] Fix | Delete
# call our (possibly overridden) exit function
[468] Fix | Delete
self.exithook()
[469] Fix | Delete
[470] Fix | Delete
def EOFhook(self):
[471] Fix | Delete
"Classes using rpc client/server can override to augment EOF action"
[472] Fix | Delete
pass
[473] Fix | Delete
[474] Fix | Delete
#----------------- end class SocketIO --------------------
[475] Fix | Delete
[476] Fix | Delete
class RemoteObject(object):
[477] Fix | Delete
# Token mix-in class
[478] Fix | Delete
pass
[479] Fix | Delete
[480] Fix | Delete
def remoteref(obj):
[481] Fix | Delete
oid = id(obj)
[482] Fix | Delete
objecttable[oid] = obj
[483] Fix | Delete
return RemoteProxy(oid)
[484] Fix | Delete
[485] Fix | Delete
class RemoteProxy(object):
[486] Fix | Delete
[487] Fix | Delete
def __init__(self, oid):
[488] Fix | Delete
self.oid = oid
[489] Fix | Delete
[490] Fix | Delete
class RPCHandler(SocketServer.BaseRequestHandler, SocketIO):
[491] Fix | Delete
[492] Fix | Delete
debugging = False
[493] Fix | Delete
location = "#S" # Server
[494] Fix | Delete
[495] Fix | Delete
def __init__(self, sock, addr, svr):
[496] Fix | Delete
svr.current_handler = self ## cgt xxx
[497] Fix | Delete
SocketIO.__init__(self, sock)
[498] Fix | Delete
SocketServer.BaseRequestHandler.__init__(self, sock, addr, svr)
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function