summaryrefslogtreecommitdiffstats
path: root/Tools/idle/RemoteInterp.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/idle/RemoteInterp.py')
-rw-r--r--Tools/idle/RemoteInterp.py341
1 files changed, 0 insertions, 341 deletions
diff --git a/Tools/idle/RemoteInterp.py b/Tools/idle/RemoteInterp.py
deleted file mode 100644
index e6f7671..0000000
--- a/Tools/idle/RemoteInterp.py
+++ /dev/null
@@ -1,341 +0,0 @@
-import select
-import socket
-import struct
-import sys
-import types
-
-VERBOSE = None
-
-class SocketProtocol:
- """A simple protocol for sending strings across a socket"""
- BUF_SIZE = 8192
-
- def __init__(self, sock):
- self.sock = sock
- self._buffer = ''
- self._closed = 0
-
- def close(self):
- self._closed = 1
- self.sock.close()
-
- def send(self, buf):
- """Encode buf and write it on the socket"""
- if VERBOSE:
- VERBOSE.write('send %d:%s\n' % (len(buf), `buf`))
- self.sock.send('%d:%s' % (len(buf), buf))
-
- def receive(self, timeout=0):
- """Get next complete string from socket or return None
-
- Raise EOFError on EOF
- """
- buf = self._read_from_buffer()
- if buf is not None:
- return buf
- recvbuf = self._read_from_socket(timeout)
- if recvbuf is None:
- return None
- if recvbuf == '' and self._buffer == '':
- raise EOFError
- if VERBOSE:
- VERBOSE.write('recv %s\n' % `recvbuf`)
- self._buffer = self._buffer + recvbuf
- r = self._read_from_buffer()
- return r
-
- def _read_from_socket(self, timeout):
- """Does not block"""
- if self._closed:
- return ''
- if timeout is not None:
- r, w, x = select.select([self.sock], [], [], timeout)
- if timeout is None or r:
- return self.sock.recv(self.BUF_SIZE)
- else:
- return None
-
- def _read_from_buffer(self):
- buf = self._buffer
- i = buf.find(':')
- if i == -1:
- return None
- buflen = int(buf[:i])
- enclen = i + 1 + buflen
- if len(buf) >= enclen:
- s = buf[i+1:enclen]
- self._buffer = buf[enclen:]
- return s
- else:
- self._buffer = buf
- return None
-
-# helpers for registerHandler method below
-
-def get_methods(obj):
- methods = []
- for name in dir(obj):
- attr = getattr(obj, name)
- if callable(attr):
- methods.append(name)
- if type(obj) == types.InstanceType:
- methods = methods + get_methods(obj.__class__)
- if type(obj) == types.ClassType:
- for super in obj.__bases__:
- methods = methods + get_methods(super)
- return methods
-
-class CommandProtocol:
- def __init__(self, sockp):
- self.sockp = sockp
- self.seqno = 0
- self.handlers = {}
-
- def close(self):
- self.sockp.close()
- self.handlers.clear()
-
- def registerHandler(self, handler):
- """A Handler is an object with handle_XXX methods"""
- for methname in get_methods(handler):
- if methname[:7] == "handle_":
- name = methname[7:]
- self.handlers[name] = getattr(handler, methname)
-
- def send(self, cmd, arg='', seqno=None):
- if arg:
- msg = "%s %s" % (cmd, arg)
- else:
- msg = cmd
- if seqno is None:
- seqno = self.get_seqno()
- msgbuf = self.encode_seqno(seqno) + msg
- self.sockp.send(msgbuf)
- if cmd == "reply":
- return
- reply = self.sockp.receive(timeout=None)
- r_cmd, r_arg, r_seqno = self._decode_msg(reply)
- assert r_seqno == seqno and r_cmd == "reply", "bad reply"
- return r_arg
-
- def _decode_msg(self, msg):
- seqno = self.decode_seqno(msg[:self.SEQNO_ENC_LEN])
- msg = msg[self.SEQNO_ENC_LEN:]
- parts = msg.split(" ", 2)
- if len(parts) == 1:
- cmd = msg
- arg = ''
- else:
- cmd = parts[0]
- arg = parts[1]
- return cmd, arg, seqno
-
- def dispatch(self):
- msg = self.sockp.receive()
- if msg is None:
- return
- cmd, arg, seqno = self._decode_msg(msg)
- self._current_reply = seqno
- h = self.handlers.get(cmd, self.default_handler)
- try:
- r = h(arg)
- except TypeError, msg:
- raise TypeError, "handle_%s: %s" % (cmd, msg)
- if self._current_reply is None:
- if r is not None:
- sys.stderr.write("ignoring %s return value type %s\n" % \
- (cmd, type(r).__name__))
- return
- if r is None:
- r = ''
- if type(r) != types.StringType:
- raise ValueError, "invalid return type for %s" % cmd
- self.send("reply", r, seqno=seqno)
-
- def reply(self, arg=''):
- """Send a reply immediately
-
- otherwise reply will be sent when handler returns
- """
- self.send("reply", arg, self._current_reply)
- self._current_reply = None
-
- def default_handler(self, arg):
- sys.stderr.write("WARNING: unhandled message %s\n" % arg)
- return ''
-
- SEQNO_ENC_LEN = 4
-
- def get_seqno(self):
- seqno = self.seqno
- self.seqno = seqno + 1
- return seqno
-
- def encode_seqno(self, seqno):
- return struct.pack("I", seqno)
-
- def decode_seqno(self, buf):
- return struct.unpack("I", buf)[0]
-
-
-class StdioRedirector:
- """Redirect sys.std{in,out,err} to a set of file-like objects"""
-
- def __init__(self, stdin, stdout, stderr):
- self.stdin = stdin
- self.stdout = stdout
- self.stderr = stderr
-
- def redirect(self):
- self.save()
- sys.stdin = self.stdin
- sys.stdout = self.stdout
- sys.stderr = self.stderr
-
- def save(self):
- self._stdin = sys.stdin
- self._stdout = sys.stdout
- self._stderr = sys.stderr
-
- def restore(self):
- sys.stdin = self._stdin
- sys.stdout = self._stdout
- sys.stderr = self._stderr
-
-class IOWrapper:
- """Send output from a file-like object across a SocketProtocol
-
- XXX Should this be more tightly integrated with the CommandProtocol?
- """
-
- def __init__(self, name, cmdp):
- self.name = name
- self.cmdp = cmdp
- self.buffer = []
-
-class InputWrapper(IOWrapper):
- def write(self, buf):
- # XXX what should this do on Windows?
- raise IOError, (9, '[Errno 9] Bad file descriptor')
-
- def read(self, arg=None):
- if arg is not None:
- if arg <= 0:
- return ''
- else:
- arg = 0
- return self.cmdp.send(self.name, "read,%s" % arg)
-
- def readline(self):
- return self.cmdp.send(self.name, "readline")
-
-class OutputWrapper(IOWrapper):
- def write(self, buf):
- self.cmdp.send(self.name, buf)
-
- def read(self, arg=None):
- return ''
-
-class RemoteInterp:
- def __init__(self, sock):
- self._sock = SocketProtocol(sock)
- self._cmd = CommandProtocol(self._sock)
- self._cmd.registerHandler(self)
-
- def run(self):
- try:
- while 1:
- self._cmd.dispatch()
- except EOFError:
- pass
-
- def handle_execfile(self, arg):
- self._cmd.reply()
- io = StdioRedirector(InputWrapper("stdin", self._cmd),
- OutputWrapper("stdout", self._cmd),
- OutputWrapper("stderr", self._cmd))
- io.redirect()
- execfile(arg, {'__name__':'__main__'})
- io.restore()
- self._cmd.send("terminated")
-
- def handle_quit(self, arg):
- self._cmd.reply()
- self._cmd.close()
-
-def startRemoteInterp(id):
- import os
- # UNIX domain sockets are simpler for starters
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.bind("/var/tmp/ri.%s" % id)
- try:
- sock.listen(1)
- cli, addr = sock.accept()
- rinterp = RemoteInterp(cli)
- rinterp.run()
- finally:
- os.unlink("/var/tmp/ri.%s" % id)
-
-class RIClient:
- """Client of the remote interpreter"""
- def __init__(self, sock):
- self._sock = SocketProtocol(sock)
- self._cmd = CommandProtocol(self._sock)
- self._cmd.registerHandler(self)
-
- def execfile(self, file):
- self._cmd.send("execfile", file)
-
- def run(self):
- try:
- while 1:
- self._cmd.dispatch()
- except EOFError:
- pass
-
- def handle_stdout(self, buf):
- sys.stdout.write(buf)
-## sys.stdout.flush()
-
- def handle_stderr(self, buf):
- sys.stderr.write(buf)
-
- def handle_stdin(self, arg):
- if arg == "readline":
- return sys.stdin.readline()
- i = arg.find(",") + 1
- bytes = int(arg[i:])
- if bytes == 0:
- return sys.stdin.read()
- else:
- return sys.stdin.read(bytes)
-
- def handle_terminated(self, arg):
- self._cmd.reply()
- self._cmd.send("quit")
- self._cmd.close()
-
-def riExec(id, file):
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.connect("/var/tmp/ri.%s" % id)
- cli = RIClient(sock)
- cli.execfile(file)
- cli.run()
-
-if __name__ == "__main__":
- import getopt
-
- SERVER = 1
- opts, args = getopt.getopt(sys.argv[1:], 'cv')
- for o, v in opts:
- if o == '-c':
- SERVER = 0
- elif o == '-v':
- VERBOSE = sys.stderr
- id = args[0]
-
- if SERVER:
- startRemoteInterp(id)
- else:
- file = args[1]
- riExec(id, file)