diff options
Diffstat (limited to 'Lib/idlelib/rpc.py')
-rw-r--r-- | Lib/idlelib/rpc.py | 180 |
1 files changed, 71 insertions, 109 deletions
diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py index aa8cbd3..43328e7 100644 --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -5,7 +5,7 @@ connect to the Idle process, which listens for the connection. Since Idle has only one client per server, this was not a limitation. +---------------------------------+ +-------------+ - | socketserver.BaseRequestHandler | | SocketIO | + | SocketServer.BaseRequestHandler | | SocketIO | +---------------------------------+ +-------------+ ^ | register() | | | unregister()| @@ -26,56 +26,52 @@ See the Idle run.main() docstring for further information on how this was accomplished in Idle. """ -import builtins -import copyreg -import io -import marshal + +import sys import os -import pickle -import queue -import select import socket -import socketserver +import select +import SocketServer import struct -import sys +import cPickle as pickle import threading +import Queue import traceback +import copy_reg import types +import marshal + def unpickle_code(ms): - "Return code object from marshal string ms." co = marshal.loads(ms) assert isinstance(co, types.CodeType) return co def pickle_code(co): - "Return unpickle function and tuple with marshalled co code object." assert isinstance(co, types.CodeType) ms = marshal.dumps(co) return unpickle_code, (ms,) -def dumps(obj, protocol=None): - "Return pickled (or marshalled) string for obj." - # IDLE passes 'None' to select pickle.DEFAULT_PROTOCOL. - f = io.BytesIO() - p = CodePickler(f, protocol) - p.dump(obj) - return f.getvalue() - +# XXX KBK 24Aug02 function pickling capability not used in Idle +# def unpickle_function(ms): +# return ms -class CodePickler(pickle.Pickler): - dispatch_table = {types.CodeType: pickle_code, **copyreg.dispatch_table} +# def pickle_function(fn): +# assert isinstance(fn, type.FunctionType) +# return repr(fn) +copy_reg.pickle(types.CodeType, pickle_code, unpickle_code) +# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function) BUFSIZE = 8*1024 LOCALHOST = '127.0.0.1' -class RPCServer(socketserver.TCPServer): +class RPCServer(SocketServer.TCPServer): def __init__(self, addr, handlerclass=None): if handlerclass is None: handlerclass = RPCHandler - socketserver.TCPServer.__init__(self, addr, handlerclass) + SocketServer.TCPServer.__init__(self, addr, handlerclass) def server_bind(self): "Override TCPServer method, no bind() phase for connecting entity" @@ -108,21 +104,21 @@ class RPCServer(socketserver.TCPServer): raise except: erf = sys.__stderr__ - print('\n' + '-'*40, file=erf) - print('Unhandled server exception!', file=erf) - print('Thread: %s' % threading.current_thread().name, file=erf) - print('Client Address: ', client_address, file=erf) - print('Request: ', repr(request), file=erf) + print>>erf, '\n' + '-'*40 + print>>erf, 'Unhandled server exception!' + print>>erf, 'Thread: %s' % threading.currentThread().getName() + print>>erf, 'Client Address: ', client_address + print>>erf, 'Request: ', repr(request) traceback.print_exc(file=erf) - print('\n*** Unrecoverable, server exiting!', file=erf) - print('-'*40, file=erf) + print>>erf, '\n*** Unrecoverable, server exiting!' + print>>erf, '-'*40 os._exit(0) #----------------- end class RPCServer -------------------- objecttable = {} -request_queue = queue.Queue(0) -response_queue = queue.Queue(0) +request_queue = Queue.Queue(0) +response_queue = Queue.Queue(0) class SocketIO(object): @@ -130,7 +126,7 @@ class SocketIO(object): nextseq = 0 def __init__(self, sock, objtable=None, debugging=None): - self.sockthread = threading.current_thread() + self.sockthread = threading.currentThread() if debugging is not None: self.debugging = debugging self.sock = sock @@ -153,10 +149,10 @@ class SocketIO(object): def debug(self, *args): if not self.debugging: return - s = self.location + " " + str(threading.current_thread().name) + s = self.location + " " + str(threading.currentThread().getName()) for a in args: s = s + " " + str(a) - print(s, file=sys.__stderr__) + print>>sys.__stderr__, s def register(self, oid, object): self.objtable[oid] = object @@ -200,16 +196,12 @@ class SocketIO(object): return ("ERROR", "Unsupported message type: %s" % how) except SystemExit: raise - except KeyboardInterrupt: + except socket.error: raise - except OSError: - raise - except Exception as ex: - return ("CALLEXC", ex) except: msg = "*** Internal Error: rpc.py:SocketIO.localcall()\n\n"\ " Object: %s \n Method: %s \n Args: %s\n" - print(msg % (oid, method, args), file=sys.__stderr__) + print>>sys.__stderr__, msg % (oid, method, args) traceback.print_exc(file=sys.__stderr__) return ("EXCEPTION", None) @@ -226,7 +218,7 @@ class SocketIO(object): def asynccall(self, oid, methodname, args, kwargs): request = ("CALL", (oid, methodname, args, kwargs)) seq = self.newseq() - if threading.current_thread() != self.sockthread: + if threading.currentThread() != self.sockthread: cvar = threading.Condition() self.cvars[seq] = cvar self.debug(("asynccall:%d:" % seq), oid, methodname, args, kwargs) @@ -236,7 +228,7 @@ class SocketIO(object): def asyncqueue(self, oid, methodname, args, kwargs): request = ("QUEUE", (oid, methodname, args, kwargs)) seq = self.newseq() - if threading.current_thread() != self.sockthread: + if threading.currentThread() != self.sockthread: cvar = threading.Condition() self.cvars[seq] = cvar self.debug(("asyncqueue:%d:" % seq), oid, methodname, args, kwargs) @@ -264,11 +256,8 @@ class SocketIO(object): return None if how == "ERROR": self.debug("decoderesponse: Internal ERROR:", what) - raise RuntimeError(what) - if how == "CALLEXC": - self.debug("decoderesponse: Call Exception:", what) - raise what - raise SystemError(how, what) + raise RuntimeError, what + raise SystemError, (how, what) def decode_interrupthook(self): "" @@ -298,14 +287,14 @@ class SocketIO(object): def _proxify(self, obj): if isinstance(obj, RemoteProxy): return RPCProxy(self, obj.oid) - if isinstance(obj, list): - return list(map(self._proxify, obj)) + if isinstance(obj, types.ListType): + return map(self._proxify, obj) # XXX Check for other types -- not currently needed return obj def _getresponse(self, myseq, wait): self.debug("_getresponse:myseq:", myseq) - if threading.current_thread() is self.sockthread: + if threading.currentThread() is self.sockthread: # this thread does all reading of requests or responses while 1: response = self.pollresponse(myseq, wait) @@ -332,9 +321,9 @@ class SocketIO(object): def putmessage(self, message): self.debug("putmessage:%d:" % message[0]) try: - s = dumps(message) + s = pickle.dumps(message) except pickle.PicklingError: - print("Cannot pickle:", repr(message), file=sys.__stderr__) + print >>sys.__stderr__, "Cannot pickle:", repr(message) raise s = struct.pack("<i", len(s)) + s while len(s) > 0: @@ -342,40 +331,40 @@ class SocketIO(object): r, w, x = select.select([], [self.sock], []) n = self.sock.send(s[:BUFSIZE]) except (AttributeError, TypeError): - raise OSError("socket no longer exists") + raise IOError, "socket no longer exists" s = s[n:] - buff = b'' + buffer = "" bufneed = 4 bufstate = 0 # meaning: 0 => reading count; 1 => reading data def pollpacket(self, wait): self._stage0() - if len(self.buff) < self.bufneed: + if len(self.buffer) < self.bufneed: r, w, x = select.select([self.sock.fileno()], [], [], wait) if len(r) == 0: return None try: s = self.sock.recv(BUFSIZE) - except OSError: + except socket.error: raise EOFError if len(s) == 0: raise EOFError - self.buff += s + self.buffer += s self._stage0() return self._stage1() def _stage0(self): - if self.bufstate == 0 and len(self.buff) >= 4: - s = self.buff[:4] - self.buff = self.buff[4:] + if self.bufstate == 0 and len(self.buffer) >= 4: + s = self.buffer[:4] + self.buffer = self.buffer[4:] self.bufneed = struct.unpack("<i", s)[0] self.bufstate = 1 def _stage1(self): - if self.bufstate == 1 and len(self.buff) >= self.bufneed: - packet = self.buff[:self.bufneed] - self.buff = self.buff[self.bufneed:] + if self.bufstate == 1 and len(self.buffer) >= self.bufneed: + packet = self.buffer[:self.bufneed] + self.buffer = self.buffer[self.bufneed:] self.bufneed = 4 self.bufstate = 0 return packet @@ -387,10 +376,10 @@ class SocketIO(object): try: message = pickle.loads(packet) except pickle.UnpicklingError: - print("-----------------------", file=sys.__stderr__) - print("cannot unpickle packet:", repr(packet), file=sys.__stderr__) + print >>sys.__stderr__, "-----------------------" + print >>sys.__stderr__, "cannot unpickle packet:", repr(packet) traceback.print_stack(file=sys.__stderr__) - print("-----------------------", file=sys.__stderr__) + print >>sys.__stderr__, "-----------------------" raise return message @@ -421,7 +410,7 @@ class SocketIO(object): # send queued response if there is one available try: qmsg = response_queue.get(0) - except queue.Empty: + except Queue.Empty: pass else: seq, response = qmsg @@ -490,20 +479,17 @@ class RemoteObject(object): # Token mix-in class pass - def remoteref(obj): oid = id(obj) objecttable[oid] = obj return RemoteProxy(oid) - class RemoteProxy(object): def __init__(self, oid): self.oid = oid - -class RPCHandler(socketserver.BaseRequestHandler, SocketIO): +class RPCHandler(SocketServer.BaseRequestHandler, SocketIO): debugging = False location = "#S" # Server @@ -511,16 +497,15 @@ class RPCHandler(socketserver.BaseRequestHandler, SocketIO): def __init__(self, sock, addr, svr): svr.current_handler = self ## cgt xxx SocketIO.__init__(self, sock) - socketserver.BaseRequestHandler.__init__(self, sock, addr, svr) + SocketServer.BaseRequestHandler.__init__(self, sock, addr, svr) def handle(self): - "handle() method required by socketserver" + "handle() method required by SocketServer" self.mainloop() def get_remote_proxy(self, oid): return RPCProxy(self, oid) - class RPCClient(SocketIO): debugging = False @@ -536,17 +521,16 @@ class RPCClient(SocketIO): def accept(self): working_sock, address = self.listening_sock.accept() if self.debugging: - print("****** Connection request from ", address, file=sys.__stderr__) + print>>sys.__stderr__, "****** Connection request from ", address if address[0] == LOCALHOST: SocketIO.__init__(self, working_sock) else: - print("** Invalid host: ", address, file=sys.__stderr__) - raise OSError + print>>sys.__stderr__, "** Invalid host: ", address + raise socket.error def get_remote_proxy(self, oid): return RPCProxy(self, oid) - class RPCProxy(object): __methods = None @@ -568,7 +552,7 @@ class RPCProxy(object): (name,), {}) return value else: - raise AttributeError(name) + raise AttributeError, name def __getattributes(self): self.__attributes = self.sockio.remotecall(self.oid, @@ -583,19 +567,20 @@ def _getmethods(obj, methods): # Adds names to dictionary argument 'methods' for name in dir(obj): attr = getattr(obj, name) - if callable(attr): + if hasattr(attr, '__call__'): methods[name] = 1 - if isinstance(obj, type): + if type(obj) == types.InstanceType: + _getmethods(obj.__class__, methods) + if type(obj) == types.ClassType: for super in obj.__bases__: _getmethods(super, methods) def _getattributes(obj, attributes): for name in dir(obj): attr = getattr(obj, name) - if not callable(attr): + if not hasattr(attr, '__call__'): attributes[name] = 1 - class MethodProxy(object): def __init__(self, sockio, oid, name): @@ -603,33 +588,10 @@ class MethodProxy(object): self.oid = oid self.name = name - def __call__(self, /, *args, **kwargs): + def __call__(self, *args, **kwargs): value = self.sockio.remotecall(self.oid, self.name, args, kwargs) return value # XXX KBK 09Sep03 We need a proper unit test for this module. Previously # existing test code was removed at Rev 1.27 (r34098). - -def displayhook(value): - """Override standard display hook to use non-locale encoding""" - if value is None: - return - # Set '_' to None to avoid recursion - builtins._ = None - text = repr(value) - try: - sys.stdout.write(text) - except UnicodeEncodeError: - # let's use ascii while utf8-bmp codec doesn't present - encoding = 'ascii' - bytes = text.encode(encoding, 'backslashreplace') - text = bytes.decode(encoding, 'strict') - sys.stdout.write(text) - sys.stdout.write("\n") - builtins._ = value - - -if __name__ == '__main__': - from unittest import main - main('idlelib.idle_test.test_rpc', verbosity=2,) |